龙卷风/扭曲的纽伯在这里。首先,我只想确认我所知道的(如果我错了,请更正并详细说明):
为了在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函数,只需为其提供callback关键字参数)?我似乎得到了正确的结果,但是我的方式真的是异步运行吗?以这种方式使用IOLoop有任何并发症/问题吗?
我实际上在其他线程上发布了一些相关的问题
Is it possible to use tornado's gen.engine and gen.Task with twisted?
Using Tornado and Twisted at the same time
答案告诉我应该“包装” inlineCallback函数。我想知道添加callback关键字是否足以“包装”扭曲的函数以适合Tornado。
提前致谢
最佳答案
您所做的大部分都很好:添加callback
参数足以使函数可用于gen.Task。唯一棘手的部分是异常处理:您需要从except
或finally
块运行回调以确保它始终发生,并且可能应返回某种值来指示操作是否成功(异常使用非龙卷风代码时,请不要可靠地通过gen.Task
)
包装方法(我在Is it possible to use tornado's gen.engine and gen.Task with twisted?中发布了)有两个优点:它可以直接与大多数Twisted代码一起使用(因为Twisted函数通常没有callback
参数),并且异常的工作方式更像您期望的那样(内部函数中引发的异常将传播到外部函数)。
关于python - 将Twisted的@inlineCallbacks与Tornado的@ gen.engine一起使用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19506903/