Приложение WSGI выполняется в собственном потоке (или процессе). При работе в WSGI-контейнере Twisted это другой поток, в котором работает реактор. Большинство API-интерфейсов Twisted не являются потокобезопасными: их можно вызывать только в потоке реактора.
Таким образом, основной способ вызова Twisted API из приложения WSGI — использование reactor.callFromThread
, который является потокобезопасным и вызывает вызов функции в потоке реактора:
...
reactor.callFromThread(pbRemote.callRemote, "someMethod", some, args)
Однако это отбрасывает результат, который вы, вероятно, хотите. Тем не менее, создать API поверх reactor.callFromThread
, сохраняющий результат, просто, и в Twisted тоже есть такая реализация:
from twisted.internet.threads import blockingCallFromThread
...
result = blockingCallFromThread(reactor, pbRemote.callRemote, "someMethod", some, args)
Этот вызов будет заблокирован до тех пор, пока не сработает Deferred, возвращенный callRemote
, а затем он вернет результат этого Deferred.
Если вы хотите сделать звонок, выполнить какую-то другую работу, а затем дождаться завершения разговора, вам придется проявить немного творчества. Вам нужно сделать вызов и получить фактический Deferred
, который он возвращает, но не блокировать его:
resultHolder = blockingCallFromThread(
reactor, lambda: [pbRemote.callRemote("someMethod", some, args)])
И тогда вы можете делать любую другую работу, которую вам нужно сделать. И когда вы будете готовы дождаться результата вызова PB:
result = blockingCallFromThread(reactor, lambda: resultHolder[0])
Все это гораздо более неудобно, чем использование Twisted в однопоточном сценарии, поэтому действительно может быть проще использовать собственные API-интерфейсы Twisted Web, а не создавать приложение WSGI. Помните, что одной из основных целей WSGI является обеспечение возможности разработки приложений, переносимых между разными серверами — Twisted, Apache и т. д. Если вы на самом деле используете Twisted API в своем приложении WSGI, то оно вообще не является переносимым.
person
Jean-Paul Calderone
schedule
22.01.2012