Скрученная обработка асинхронных запросов

Как я могу выполнять асинхронную обработку запросов в Twisted, как в Node.js?

Я написал пример с Twisted, но мое приложение все еще ждало ответа от долгой работы (я эмулирую это с помощью time.sleep).

Также я не понимаю, как я могу правильно использовать Reactor.callLater.

Это мой образец скрученного приложения.


from twisted.web import server
from twisted.web.resource import Resource
from twisted.internet import reactor
from twisted.internet.defer import Deferred
import time

class Hello(Resource):
    def getChild(self, name, request):
        if name == '':
            return self
        print name
        return Resource.getChild(self, name, request)

    def render_GET(self, req):
        d = Deferred()
        reactor.callLater(2, d.callback, None)
        d.addCallback(lambda _: self.say_hi(req))
        return server.NOT_DONE_YET

    def say_hi(self, req):
        req.setHeader("content-type", "text/html")
        time.sleep(5)
        req.write("hello!")
        req.finish()

class Hello2(Resource):
    isLeaf = True
    def render_GET(self, req):
        req.setHeader("content-type", "text/html")
        return "hello2!"

root = Hello()
root.putChild("2", Hello2())
reactor.listenTCP(8080, server.Site(root))
reactor.run()

Изменить: Теперь вопрос в том, как написать код синхронизации? Пожалуйста пример.


person Stan    schedule 16.11.2011    source источник
comment
time.sleep() блокирует вызов. Если у вас тяжелая обработка - попробуйте DeferToThread().   -  person Pill    schedule 16.11.2011
comment
Но в питоне много блокирующих библиотек. Что рекомендуется использовать для таких библиотек?   -  person Stan    schedule 16.11.2011
comment
Да - печально, но факт. Как я уже говорил выше - можно попробовать сделать с помощью DeferToThread, или поискать какие-нибудь асинхронные аналоги.   -  person Pill    schedule 16.11.2011
comment
Что означает лайк в Node.js? Блокировка есть блокировка, Node.js не предотвращает ее волшебным образом.   -  person Jean-Paul Calderone    schedule 16.11.2011
comment
Хм, согласен. Плюс к Node.js есть множество асинхронных библиотек.   -  person Stan    schedule 16.11.2011
comment
Ниже приведен пример, демонстрирующий, как можно справиться с блокировкой кода, интенсивно использующего ЦП.   -  person jfs    schedule 17.11.2011


Ответы (1)


Ты уже делаешь это... вроде.

Ваша проблема здесь в том, что time.sleep() является блокирующим вызовом и, следовательно, остановит весь ваш сервер.

Если вы используете его в качестве замены для чего-то, что выполняет сетевой ввод-вывод (например, urllib), обычно лучше всего выполнять ввод-вывод с помощью Twisted (например, twisted.web.client.getPage), а не пытаться сделать что-то с блокирующий код. Twisted имеет множество клиентских библиотек. Эти библиотеки обычно дают вам Deferred, с которым вы уже работаете.

Если вы используете его как замену для фактического ожидания, вы можете создать Deferred, который ожидает с deferLater.

Если вы используете его в качестве замены для чего-то интенсивного ЦП, которое не захватывает GIL (например, кодирование изображений PIL или собственный синтаксический анализатор XML) или существующий собственный/проприетарный уровень ввода-вывода (например, Oracle или MSSQL привязки базы данных), которые вы не хотели бы переписывать для правильного использования Twisted, вы можете вызвать его с помощью deferToThread.

Как бы вы ни получили Deferred, вы почти готовы справиться с этим. Вам просто нужно настроить say_hi, чтобы вернуть один:

def say_hi(self, req):
    req.setHeader("content-type", "text/html")
    d = getADeferredSomehow()
    def done(result):
        req.write("hello!")
        req.finish()
    return d.addBoth(done)
person Glyph    schedule 16.11.2011
comment
Спасибо за ответ. time.sleep — это просто заглушка для блокировки вызова. Я попытался эмулировать вызов блокирующей библиотеки (например, множество библиотек в python) и узнать, как написать неблокирующее приложение. - person Stan; 17.11.2011