Python, Twisted, Django, реактор.run () вызывает проблемы - PullRequest
2 голосов
/ 26 декабря 2010

У меня есть веб-приложение Django. У меня также есть сервер заклинаний, написанный с использованием витой, работающей на той же машине, на которой установлен 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() вызывает проблему. Так как это цикл событий. В следующий раз, когда Джанго выполнит этот код, я не смогу подключиться к серверу. Как с этим справиться?

Ответы [ 3 ]

4 голосов
/ 16 января 2011

Два приведенных выше ответа верны. Однако, учитывая, что вы уже реализовали правописание сервер , тогда запустите его как один . Вы можете начать, запустив его на той же машине, что и отдельный процесс - на localhost:PORT. Сейчас кажется, что у вас уже есть очень простой интерфейс двоичного протокола - вы можете реализовать такой же простой клиент Python, используя стандартный интерфейс lib * 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)

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

3 голосов
/ 27 декабря 2010

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

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

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

1 голос
/ 26 декабря 2010

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

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

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

...