1

Tornado/Twisted newb 在这里。首先我只是想确认一下我所知道的(如果我错了,请更正并详细说明):

为了在 Tornado 中使用 @gen.engine 和 gen.Task,我需要提供以下 gen.Task() 函数:

  • 异步开始
  • 有关键字参数“回调”
  • 在最后调用回调函数

换句话说,该函数应如下所示:

def function(arg1, arg2, ... , callback=None):

    # asynchronous stuff here ...

    callback()

我会这样称呼它(简单的例子):

@gen.engine
def coroutine_call():

    yield gen.Task(function, arg1, arg2)

现在我处于一种奇怪的情况,我必须在 Tornado 系统中使用 Twisted 来异步客户端调用服务器(因为 Tornado 显然不支持它)。

所以我在 Twisted 中写了一个函数(例如连接到服务器):

import tornado.platform.twisted
tornado.platform.twisted.install()
from twisted.web.xmlrpc import Proxy

class AsyncConnection():
    def __init__(self, hostname):
        self.proxy = Proxy(hostname)
        self.token = False

    @defer.inlineCallbacks
    def login(self, user, passwd, callback=None):
        """Login to server using given username and password"""

        self.token = yield self.proxy.callRemote('login', user, passwd) # twisted function
        callback()

如果我像这样运行它:

@gen.engine
def test():

    conn = AsyncConnection("192.168.11.11")
    yield gen.Task(conn.login, "user","pwd")
    print conn.token

if __name__ == '__main__':
    test()
    tornado.ioloop.IOLoop.instance().start()

我确实得到了我想要的令牌。但我的问题是:

我知道 Twisted 和 Tornado 可以共享同一个 IOLoop。但是我可以这样做吗(即在 gen.Task 中使用@defer.inlineCallbacks 函数,只需给它回调关键字参数)?我似乎得到了正确的结果,但我的方式真的是异步运行的吗?IOLoop 这种方式有什么并发症/问题吗?

我实际上在其他线程上发布了一些相关的问题

是否可以使用 tornado 的 gen.engine 和 gen.Task 扭曲?

同时使用 Tornado 和 Twisted

答案告诉我应该“包装” inlineCallback 函数。我想知道添加回调关键字是否足以“包装”扭曲的函数以适合 Tornado。

提前致谢

4

1 回答 1

2

你所做的大部分都很好:添加一个callback参数就足以使一个函数与 gen.Task 一起使用。唯一棘手的部分是异常处理:您需要从exceptorfinally块运行回调以确保它总是发生,并且可能应该返回某种值来指示操作是否成功(异常不能可靠地通过gen.Task当您使用非 Tornado 代码时)

包装方法(我发布在Is it possible to use tornado's gen.engine and gen.Task with twisted?)有两个优点:它可以直接与大多数 Twisted 代码一起使用(因为 Twisted 函数通常没有callback参数) ,并且异常的工作方式更像您所期望的(内部函数中引发的异常将传播到外部函数)。

于 2013-10-22T15:36:46.770 回答