同时使用Tornado和Twisted

3

我处于一种奇怪的情况,必须在完全由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上工作,所以我认为这应该没问题。但是是否会有任何意想不到的后果?谢谢。

2个回答

4

看起来你想要的是Cyclone,它是一个用Python编写的Web服务器框架,实现了Tornado API作为Twisted协议。


3
不,这样行不通。在你的情况下,inlineCallbacks 直接包装了你的生成器,而 gen.engine 则包装在外面。问题是 inlineCallbacks 不知道任何有关 gen.Task 的信息,并且它会立即产生该信息(无法将其传递给 gen.engine)。
详细解释一下:如果你在 inlineCallbacks 包装的生成器中产生 obj,可能会发生两种情况:
  1. obj 是一个 Deferred,在这种情况下,控制权会返回到反应堆,直到该 Deferred 触发。
  2. 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

请查看这里,了解 inlineCallbacks 的实现方式。

正确的做法是什么?尝试使用 inlineCallbacks 或者 gen.engine(但不要同时使用两者)。将外部的 gen.Task(或者Deferred)包装成“本地”形式。我不熟悉 Tornado,但也许这个问题有所帮助

另外,您可以编写自己的装饰器,类似于 inlineCallbacks,可以处理 gen.Task


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接