实验 7:一组任务一起收尾
上一节只处理一个任务超时。现在看一组任务:如果其中一个失败,剩下的任务还要继续跑吗?
很多业务里不应该继续。比如构造一个页面时,主请求已经失败,相关的补充请求也该停掉。这就是 TaskGroup 好用的地方。
运行:
bash
python3 examples/asyncio_demos/07_taskgroup_failure.pyTaskGroup 的规则
示例里开了三个子任务:
python
async with asyncio.TaskGroup() as tg:
tg.create_task(call_service("search", 0.1, fail=True))
tg.create_task(call_service("audit", 1.0))
tg.create_task(call_service("metrics", 0.8))search 会先失败。TaskGroup 发现子任务抛异常后,会取消还没结束的兄弟任务,然后等它们执行清理代码。
裸 create_task 有什么问题
如果你这样写:
python
asyncio.create_task(call_service("audit", 1.0))这件事就离开了当前代码块。它失败了谁处理?当前请求结束了它还该不该跑?这些问题都要你自己管。
TaskGroup 把一组任务放进同一个 async with。代码块结束时,这组任务也有明确结果:要么都完成,要么失败并收拾干净。
ExceptionGroup 是什么
TaskGroup 可能同时收集多个异常,所以外面用:
python
except* RuntimeError as group:
print(len(group.exceptions))这里先记住用法即可。重点是:子任务失败不会悄悄丢在后台。
小练习
- 把
search的fail=True改成False,观察三个任务是否都正常完成。 - 把
audit的 delay 改成0.05,让它先完成,再看search失败时谁会被取消。 - 在
call_service里把except asyncio.CancelledError后面的raise删除,观察audit和metrics看起来像“自己正常结束”还是“被取消后清理”。这个练习是为了说明:清理可以做,但取消信号通常要继续传出去。