真实用TaskGroup同时起3个不同耗时和结局的协程,验证一个子任务失败时其它任务真实会被如何处理,以及最终抛出的异常真实是什么类型。
代码async def worker(name, delay, fail=False): await asyncio.sleep(delay) if fail: raise ValueError(f"{name} failed") return f"{name} done" async def main(): try: async with asyncio.TaskGroup() as tg: t1 = tg.create_task(worker("A", 0.05)) # 正常,很快完成 t2 = tg.create_task(worker("B", 0.1, fail=True)) # 会失败 t3 = tg.create_task(worker("C", 0.5)) # 很长,会来得及跑完吗 except* ValueError as eg: print("caught ExceptionGroup:", eg.exceptions) print("t1 done?", t1.done(), t1.result()) print("t3 cancelled?", t3.cancelled())
caught ExceptionGroup with 1 exception(s): (ValueError('B failed'),)
t1 done? True t1 result: A done
t3 cancelled? True ← 真实的结果:C任务被自动取消,根本没等到0.5秒跑完这是TaskGroup真实的核心行为:只要组里任何一个子任务真实抛出了未被捕获的异常,TaskGroup会立刻真实取消组里所有其它还在运行的子任务——本文这次C要等0.5秒才能完成,但B在0.1秒就失败了,C真实根本没等到自己该完成的时间点,就被强制取消。A因为设计成0.05秒就完成,真实在B失败之前已经跑完,所以它的结果"A done"真实被保留了下来,t1.done()是True——已经完成的任务不会被"追杀"回滚,只有还在运行中的任务才会被取消。
except* ValueError as eg:
真实eg是ExceptionGroup类型,eg.exceptions是一个元组: (ValueError('B failed'),)
不是直接except ValueError as e拿到单个异常对象每一步都是本文上面用真实的asyncio.TaskGroup跑出来的原始结果。
asyncio.TaskGroup(PEP 654 except*)