asyncio下cancel future后无响应问题

最近遇到一个很诡异的问题,就是在网络连接断开后,cancel了future,但是等待进程没有后续了,也没有超时,也没有异常。按官方文档来看,如果await的future被cancel了,等待的协程会报CancelledError异常才对。

最小化例子代码为:

import asyncio

async def foo(future):
    await asyncio.sleep(3)
    future.cancel()

async def bar(future):
    await future
    print("hi")

loop = asyncio.get_event_loop()
future = loop.create_future()
loop.create_task(bar(future))
loop.create_task(foo(future))
loop.run_forever()

上面的例子中,hi不会被输出,但同时也不会有Exception堆栈打印出来,原因就在于loop.create_task()不会对返回值做处理,无论是异常返回还是正常返回。

三种处理方法:

1. 自行catch,以确保异常被捕获

async def bar(future):
    try:
        await future
    except asyncio.CancelledError:
        pass

    print("hi")

2. 使用task的结束回调,查询结果

task = loop.create_task(bar(future))
task.add_done_callback(lambda x: print('cannelled: %s, done: %s' % (x.cancelled(), x.done())))

3. 使用关注运行结果的函数run_until_complete()

loop = asyncio.get_event_loop()
future = loop.create_future()
loop.create_task(foo(future))
loop.run_until_complete(bar(future))

 

发表于 02月08日 17:48   评论:0   阅读:639  



回到顶部

首页 | 关于我 | 关于本站 | 站内留言 | rss
python logo   django logo   tornado logo