documentation for asyncio.gather说
如果return_exceptions为
False
(默认),则第一个引发的异常为 立即传播到在gather()
上等待的任务。其他 aws序列中的等待项不会被取消,并将继续 运行。
但是,从一个简单的测试来看,如果在return_exceptions为False
时,如果其中一个任务引发了异常,则所有其他等待项都将被取消(或更确切地说,如果术语对我来说不清楚) ,其他待办事项仍未完成工作):
import asyncio
async def factorial(name, number, raise_exception=False):
# If raise_exception is True, will raise an exception when
# the loop counter > 3
f = 1
for i in range(2, number + 1):
print(f' Task {name}: Compute factorial({i})...')
if raise_exception and i > 3:
print(f' Task {name}: raising Exception')
raise Exception(f'Bad Task {name}')
await asyncio.sleep(1)
f *= i
print(f'==>> Task {name} DONE: factorial({number}) = {f}')
return f
async def main():
tasks = [factorial('A', 5), # this will not be finished
factorial('B', 10, raise_exception=True),
factorial('C', 2)]
try:
results = await asyncio.gather(*tasks)
print('Results:', results)
except Exception as e:
print('Got an exception:', e)
asyncio.run(main())
这段代码在做什么,只是为了使其更简单,它定义了3个任务并在它们上调用asyncio.gather()
。其中一项任务在完成另一项任务之前引发了异常,而另一项任务尚未完成。
实际上,我对文档中的内容甚至都没有任何意义-如果在gather
上等待的任务引发并捕获了异常,我什至无法获得返回的结果(即使另一个任务将以某种方式完成)。
我有什么遗漏吗?还是文档有问题?
这已在Python 3.7.2中进行了测试。
答案 0 :(得分:1)
我已经运行了您的代码,并获得了文档所期望的以下输出。
Task C: Compute factorial(2)...
Task A: Compute factorial(2)...
Task B: Compute factorial(2)...
==>> Task C DONE: factorial(2) = 2
Task A: Compute factorial(3)...
Task B: Compute factorial(3)...
Task A: Compute factorial(4)...
Task B: Compute factorial(4)...
Task B: raising Exception
Got an exception: Bad Task B
Task A: Compute factorial(5)...
==>> Task A DONE: factorial(5) = 120
await asyncio.gater()
立即返回,print('Got an exception:', e)
返回屏幕。正如@deceze所说,
您的程序在捕获到异常后立即退出,并返回main()
。因此,终止任务A和C的原因是整个过程死亡,而不是因为取消。
要解决此问题,请将await asyncio.sleep(20)
添加到main()
函数的末尾。