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 上工作,所以我认为这应该没问题。会不会有什么不可预见的后果?提前致谢。

4

2 回答 2

4

看起来你想要的是Cyclone,这是一个 Python 的 Web 服务器框架,将 Tornado API 实现为 Twisted 协议。

于 2013-10-21T19:05:39.160 回答
3

不,这行不通。在您的情况下inlineCallbacks,直接包裹在您的发电机周围并gen.engine包裹在外面。问题是它inlineCallbacks什么都不知道gen.Task,它会立即产生它(它无法将它传递给gen.engine)。

详细说明:如果您objinlineCallbacks-wrapped 生成器中 yield ,可能会发生两件事:

  1. objDeferred这种情况下,控制权将返回到反应堆,直到它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实施。

这样做的正确方法是什么?尝试使用其中一个inlineCallbacksgen.engine(但不能同时使用两者)。将外星人gen.Task(或Deferred)包装成“本机”形式。我不熟悉龙卷风,但也许这个问题有帮助

或者,也可以编写自己的装饰器inlineCallbacks,如句柄gen.Task

于 2013-10-21T18:54:35.070 回答