我处于一种奇怪的情况,我必须在完全由Tornado构建的系统中使用Twisted。 他们可以共享同一个IOLoop,所以我知道他们可以一起工作。我的问题是我可以在同一个函数中安全地使用他们的共同例程装饰器吗?例如:
import tornado.platform.twisted
tornado.platform.twisted.install()
...
@gen.engine
@defer.inlineCallbacks
def get(self):
...
a = yield gen.Task(getA) # tornado
b = yield proxy.callRemote(getB) # twisted
...
defer.returnValue(a + b) # twisted
他们在同一个IOLoop上工作,所以我认为这应该没问题。会有任何不可预见的后果吗?提前谢谢。
答案 0 :(得分:4)
看起来你想要的是Cyclone,一个用于Python的Web服务器框架,它将Tornado API实现为Twisted协议。
答案 1 :(得分:3)
不,这不行。在您的情况下,inlineCallbacks
直接包裹在您的生成器周围,gen.engine
被包裹在外面。问题是inlineCallbacks
对gen.Task
一无所知,它会立即产生(它无法将其传递给gen.engine
)。
详细说明:如果你在obj
包裹的生成器中产生inlineCallbacks
,可能会发生两件事:
obj
是一个Deferred
,在这种情况下,控件会返回到反应堆,直到Deferred
触发。obj
是其他内容,在这种情况下会立即将其发送回您的生成器。在您的情况下,结果将是:
a = yield gen.Task(getA) # continues right through
# a is of type gen.Task here
b = yield proxy.callRemote(getB) # waits for result of proxy.callRemote
请参阅here了解inlineCallbacks
的实施方式。
这样做的正确方法是什么?尝试使用inlineCallbacks
或gen.engine
(但不能同时使用两者)。将外星人gen.Task
(或Deferred
)包裹成“原生”形式。我不熟悉龙卷风,但也许this question helps。
或者,也可以编写自己的装饰工具,例如处理inlineCallbacks
的{{1}}。