如何从使用Tornado的IOLoop运行的协程中返回一个值?

时间:2016-12-06 18:19:06

标签: python asynchronous tornado python-3.5

我们说我有这个异步函数(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

1 个答案:

答案 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的调用者也必须是一个协程,一直到调用堆栈。

这是异步编程的铁律:为了通过网络进行通信,您的函数必须是执行yieldawait的协程,或者您必须注册回调并退出当前功能