使用Twisted的@inlineCallbacks和Tornado的@ gen.engine

时间:2013-10-22 00:10:26

标签: python asynchronous client-server twisted tornado

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

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

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

换句话说,该函数看起来像这样:

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这样的任何并发症/问题?

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

Is it possible to use tornado's gen.engine and gen.Task with twisted?

Using Tornado and Twisted at the same time

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

提前致谢

1 个答案:

答案 0 :(得分:2)

你正在做的事情很好:添加一个callback参数就足以使一个函数可以用于gen.Task。唯一棘手的部分是异常处理:您需要从exceptfinally块运行回调以确保它始终发生,并且应该返回某种值以指示操作是否成功与否(当您使用非Tornado代码时,异常无法可靠地通过gen.Task

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