【发布时间】:2020-03-23 04:59:03
【问题描述】:
如果gather 的一个任务引发异常,其他任务仍然可以继续。
嗯,这不是我所需要的。我想区分需要取消所有剩余任务的致命错误,以及不是但应该记录的错误,同时允许其他任务继续。
这是我实现这一点的失败尝试:
from asyncio import gather, get_event_loop, sleep
class ErrorThatShouldCancelOtherTasks(Exception):
pass
async def my_sleep(secs):
await sleep(secs)
if secs == 5:
raise ErrorThatShouldCancelOtherTasks('5 is forbidden!')
print(f'Slept for {secs}secs.')
async def main():
try:
sleepers = gather(*[my_sleep(secs) for secs in [2, 5, 7]])
await sleepers
except ErrorThatShouldCancelOtherTasks:
print('Fatal error; cancelling')
sleepers.cancel()
finally:
await sleep(5)
get_event_loop().run_until_complete(main())
(这里的finally await sleep是为了防止解释器立即关闭,这会自行取消所有任务)
奇怪的是,在gather 上调用cancel 实际上并没有取消它!
PS C:\Users\m> .\AppData\Local\Programs\Python\Python368\python.exe .\wtf.py
Slept for 2secs.
Fatal error; cancelling
Slept for 7secs.
我对这种行为感到非常惊讶,因为它似乎与 the documentation 相矛盾,其中指出:
asyncio.gather(*coros_or_futures, loop=None, return_exceptions=False)从给定的协程对象或未来返回一个未来的聚合结果。
(...)
取消:如果外部Future 被取消,那么所有子项(尚未完成)也被取消。 (...)
我在这里缺少什么?如何取消剩余的任务?
【问题讨论】:
标签: python python-3.x exception python-asyncio cancellation