我们说我有这个异步函数(Python 3.5)
async def func():
return '42'
我有一个Tornado I / O循环,我正在寻找一种方法来执行它。
import tornado.ioloop
ioloop = tornado.ioloop.IOLoop.current()
ioloop.start()
我可以使用IOLoop.add_callback(func)
,但我也需要返回值
关于从中检索返回值需要什么的任何想法?
修改
func
coroutine方法实际上接受一个字符串并将其发送到服务器,接收响应,正确解压缩并返回数据元组。
它是从常规(非异步)方法调用的,该方法根据其参数组装字符串,并且应该获得响应并将数据返回给调用者。
IO循环是一个类变量(可以self.
访问)
以下是一个例子:
def register(self, arg1, arg2):
# process args here
ret_value = self.ioloop.add_callback(func, arg1, arg2)
# The above line is incorrect code, just for the idea
return ret_value
第二次编辑
这是抛出AssertionError的代码的一部分:
async def _send(self, arg1):
self.ws.write_message(arg1)
resp = await self.ws.read_message()
return resp
def callback(self, future):
print('future', future.result())
def register(self, arg1):
future = self._send(arg1)
self.ioloop.add_future(future, self.callback)
我在类register
方法中使用PeriodicCallback开始执行__init__
。
future
方法中的变量register
包含<coroutine object Client._send at 0xb652c41c>
,is_future
只有在未来作为{{1}的实例时才会通过concurrent.futures.Future
检查}或tornado.concurrent.Future
答案 0 :(得分:0)
两个选项:使register
成为协程,或在回调中收到func
的返回值。
选项一:
async def register(self, arg1, arg2):
ret_value = await func(arg1, arg2)
return ret_value
选项二:
def callback(future):
try:
ret_value = future.result()
# Do something with ret_value here.
except Exception as exc:
# Log the exception or something.
print(exc)
def register(self, arg1, arg2):
future = func(arg1, arg2)
self.ioloop.add_future(future, callback)
显然,选项二很尴尬,因为您无法在原始register
函数中使用ret_value。我会去选择一个,让register
成为一个协程。然后register
的调用者也必须是一个协程,一直到调用堆栈。
这是异步编程的铁律:为了通过网络进行通信,您的函数必须是执行yield
或await
的协程,或者您必须注册回调并退出当前功能