从 asyncio 调用 Tornado 协程
Calling Tornado Coroutine from asyncio
我的主事件循环使用 asyncio,但需要调用 tornado.concurrent.Future
类型协程的库方法。尝试在协程上等待失败 RuntimeError
。
RuntimeError: Task got bad yield: <tornado.concurrent.Future object at 0x7f374abdbef0>
文档和搜索建议升级 Tornado 版本(目前使用 4.5)或使用不再生成 RuntimeError
的方法 tornado.platform.asyncio.to_asyncio_future
,而是挂在 await
上。我很想知道是否有人可以解释发生了什么。有两种主要方法,一种是使用 asyncio 调用 Tornado 协程,另一种是纯粹的 Tornado,它按预期工作。
import asyncio
from tornado import gen
from tornado.platform.asyncio import to_asyncio_future
async def coro_wrap():
tornado_fut = coro()
print(f'tornado_fut = {tornado_fut}, type({type(tornado_fut)})')
async_fut = to_asyncio_future(tornado_fut)
print(f'async_fut = {async_fut}')
res = await async_fut
print(f'done => {res}')
@gen.coroutine
def coro():
print('coro start')
yield gen.sleep(3)
print('coro end')
return 'my result'
def main():
loop = asyncio.get_event_loop()
task = loop.create_task(coro_wrap())
loop.run_until_complete(task)
print('end')
def main2():
from tornado import ioloop
loop = ioloop.IOLoop()
res = loop.run_sync(coro)
print(res)
if __name__ == '__main__':
main()
主输出
coro start
tornado_fut = <tornado.concurrent.Future object at 0x7f41493f1f28>, type(<class 'tornado.concurrent.Future'>)
async_fut = <Future pending>
main2 的输出
coro start
coro end
my result
在新版本的 Tornado 中,这很有效。
在旧版本的 tornado 中,您必须同时使用 to_asyncio_future
并在启动时调用 tornado.platform.asyncio.AsyncIOMainLoop.install()
。
我的主事件循环使用 asyncio,但需要调用 tornado.concurrent.Future
类型协程的库方法。尝试在协程上等待失败 RuntimeError
。
RuntimeError: Task got bad yield: <tornado.concurrent.Future object at 0x7f374abdbef0>
文档和搜索建议升级 Tornado 版本(目前使用 4.5)或使用不再生成 RuntimeError
的方法 tornado.platform.asyncio.to_asyncio_future
,而是挂在 await
上。我很想知道是否有人可以解释发生了什么。有两种主要方法,一种是使用 asyncio 调用 Tornado 协程,另一种是纯粹的 Tornado,它按预期工作。
import asyncio
from tornado import gen
from tornado.platform.asyncio import to_asyncio_future
async def coro_wrap():
tornado_fut = coro()
print(f'tornado_fut = {tornado_fut}, type({type(tornado_fut)})')
async_fut = to_asyncio_future(tornado_fut)
print(f'async_fut = {async_fut}')
res = await async_fut
print(f'done => {res}')
@gen.coroutine
def coro():
print('coro start')
yield gen.sleep(3)
print('coro end')
return 'my result'
def main():
loop = asyncio.get_event_loop()
task = loop.create_task(coro_wrap())
loop.run_until_complete(task)
print('end')
def main2():
from tornado import ioloop
loop = ioloop.IOLoop()
res = loop.run_sync(coro)
print(res)
if __name__ == '__main__':
main()
主输出
coro start
tornado_fut = <tornado.concurrent.Future object at 0x7f41493f1f28>, type(<class 'tornado.concurrent.Future'>)
async_fut = <Future pending>
main2 的输出
coro start
coro end
my result
在新版本的 Tornado 中,这很有效。
在旧版本的 tornado 中,您必须同时使用 to_asyncio_future
并在启动时调用 tornado.platform.asyncio.AsyncIOMainLoop.install()
。