Скрученный неблокирующий метод — как?

Мой код выглядит так:

... # class Site(Resource)
def render_POST(self,request)
   otherclass.doAssync(request.args)
   print '1'
   return "done" #that returns the HTTP response, always the same.

...

def doAssync(self,msg):
    d = defer.Deferred()
    reactor.callLater(0,self.doStuff,d,msg)
    d.addCallback(self.sucess)

def doStuff(self,d,msg):
    # do some stuff
    time.sleep(2)  #just for example
    d.callback('ok')

def sucess(msg):
    print msg

Выход:

1

ok

Пока все хорошо, но ответ HTTP (возврат 'done') происходит только после задержки (time.sleep(2)). Я могу сказать это, потому что браузер продолжает «загружаться» в течение 2 секунд.

Что я делаю неправильно?


person joaoricardo000    schedule 16.02.2012    source источник
comment
Нашел ответ: stackoverflow.com/questions/6759115/   -  person joaoricardo000    schedule 16.02.2012
comment
Будьте осторожны с тем, в каких потоках вы используете Twisted API, включая Deferreds, т.е. d.callback. Эта версия кода использует d.callback не в том потоке. Это приводит к тому, что все обратные вызовы выполняются в неправильном потоке, что, вероятно, сломает что-то, как только вы сделаете больше, чем просто распечатаете результат.   -  person Jean-Paul Calderone    schedule 16.02.2012


Ответы (1)


Что вы делаете неправильно, так это запускаете блокирующий вызов (time.sleep(2)), в то время как Twisted ожидает, что вы будете выполнять только неблокирующие операции. Вещи, которые не ждут. Поскольку у вас есть этот time.sleep(2), Twisted не может ничего делать, пока эта функция спит. Таким образом, он также не может отправлять данные в браузер.

В случае time.sleep(2) вы должны заменить его другим вызовом reactor.callLater. Предполагая, что вы действительно хотели, чтобы вызов time.sleep(2) был какой-то другой блокирующей операцией, то, как это исправить, зависит от операции. Если вы можете выполнить операцию неблокирующим способом, сделайте это. Для многих таких операций (таких как взаимодействие с базой данных) Twisted уже предлагает неблокирующие альтернативы. Если то, что вы делаете, не имеет неблокирующего интерфейса, а Twisted не имеет ему альтернативы, вам, возможно, придется запускать код в отдельном потоке (используя, например, twisted.internet.threads.deferToThread), хотя для этого требуется, чтобы ваш код был на самом деле потоком. -безопасно.

person Thomas Wouters    schedule 16.02.2012
comment
Итак, может ли он заменить reactor.callLater(...) на deferToThread(...)? - person ypercubeᵀᴹ; 16.02.2012
comment
если вы выполняете Reactor.callInThread(global_function), а global_function имеет операцию блокировки, такую ​​как чтение локального файла и обработка его содержимого. пока работает функция global_function, фабричный поток кажется затронутым, так как ответы заметно замедляются, знаете почему? - person Ajayi Oluwaseun Emmanuel; 28.08.2015