Python, Twisted, Django, Reaction.run () вызывает проблему

У меня есть веб-приложение Django. У меня также есть сервер заклинаний, написанный с использованием twisted, который работает на той же машине, что и django (работает на localhost:8090). Идея заключается в том, что когда пользователь выполняет какое-либо действие, запрос приходит к Django, который, в свою очередь, подключается к этому скрученному серверу, и сервер отправляет данные обратно в Django. Наконец, Django помещает эти данные в некоторый шаблон html и возвращает их пользователю.

Вот где у меня проблема. В моем приложении Django, когда приходит запрос, я создаю простой скрученный клиент для подключения к локально запускаемому скрученному серверу.

...
        factory = Spell_Factory(query) 
        reactor.connectTCP(AS_SERVER_HOST, AS_SERVER_PORT, factory)
        reactor.run(installSignalHandlers=0)
        print factory.results
...

reactor.run() вызывает проблему. Поскольку это цикл событий. В следующий раз, когда Django выполнит этот же код, я не смогу подключиться к серверу. Как с этим справиться?


person Srikar Appalaraju    schedule 26.12.2010    source источник


Ответы (3)


Два приведенных выше ответа верны. Однако, учитывая, что вы уже реализовали сервер проверки орфографии, запустите его как один. Вы можете запустить его на том же компьютере в качестве отдельного процесса - в localhost:PORT. Прямо сейчас кажется, что у вас уже есть очень простой интерфейс двоичного протокола - вы можете реализовать столь же простой клиент Python, используя стандартный интерфейс библиотеки socket в режиме блокировки.

Однако я предлагаю поиграться с twisted.web и открыть простой веб-интерфейс. Вы можете использовать JSON для сериализации и десериализации данных, что хорошо поддерживается Django. Вот очень быстрый пример:

import json
from twisted.web import server, resource
from twisted.python import log

class Root(resource.Resource):
    def getChild(self, path, request):
        # represents / on your web interface
        return self

class WebInterface(resource.Resource):
    isLeaf = True
    def render_GET(self, request):
        log.msg('GOT a GET request.')
        # read request.args if you need to process query args
        # ... call some internal service and get output ...
        return json.dumps(output)

class SpellingSite(server.Site):
    def __init__(self, *args, **kwargs):
        self.root = Root()
        server.Site.__init__(self, self.root, **kwargs)
        self.root.putChild('spell', WebInterface())

А для его запуска можно использовать следующий каркасный .tac файл:

from twisted.application import service, internet

site = SpellingSite()
application = service.Application('WebSpell')
# attach the service to its parent application
service_collection = service.IServiceCollection(application)
internet.TCPServer(PORT, site).setServiceParent(service_collection)

Запуск вашего сервиса в качестве другого первоклассного сервиса позволяет вам однажды запустить его на другом компьютере, если вы обнаружите необходимость - доступ к веб-интерфейсу позволяет легко масштабировать его по горизонтали и за балансировщиком нагрузки с обратным проксированием.

person rlotun    schedule 16.01.2011

reactor.run() следует вызывать только один раз во всей программе. Не думайте об этом как о «запустить этот один запрос, который у меня есть», думайте об этом как о «запустить весь Twisted».

Один из способов обойти это - запустить реактор в фоновом потоке; тогда ваше приложение django может использовать blockingCallFromThread в вашем приложении Django и используйте Twisted API, как любой блокирующий API. Тем не менее, вам потребуется немного сотрудничества со стороны вашего контейнера WSGI, потому что вам нужно будет убедиться, что этот фоновый поток Twisted запускается и останавливается в подходящее время (когда ваш интерпретатор инициализируется и прерывается, соответственно).

Вы также можете использовать Twisted в качестве контейнера WSGI, и тогда вам не нужно будет запускать или останавливать что-то особенное; blockingCallFromThread просто сразу заработает. См. Справку командной строки для twistd web --wsgi.

person Glyph    schedule 27.12.2010

Вы должны остановить реактор после получения результатов от сервера Twisted или возникновения ошибки / тайм-аута. Итак, для каждого запроса Django, который требует запроса вашего Twisted сервера, вы должны запустить реактор, а затем остановить его. Но это не поддерживается библиотекой Twisted - реактор не перезапускается. Возможные решения:

  • Используйте отдельный поток для реактора Twisted, но вам нужно будет развернуть ваше приложение django с сервером, который поддерживает длительные потоки (сейчас у меня нет ни одного из них, но вы можете легко написать свой собственный :-)).

  • Не используйте Twisted для реализации клиентского протокола, просто используйте простой модуль socket stdlib.

person andreypopp    schedule 26.12.2010