实验 6:单个任务超时
真实 I/O 不能无限等。一个接口 200ms 内没回来,你可能就要给用户降级结果,或者换备用服务。
这一节只看一个任务超时,不碰 TaskGroup。
运行:
bash
python3 examples/asyncio_demos/06_timeout_cancel.pytimeout 做了什么
示例代码:
python
try:
async with asyncio.timeout(0.2):
result = await slow_report()
except TimeoutError:
print("main: timed out")slow_report() 里会等待 1 秒。外层只给它 0.2 秒,所以到点后会发生三件事:
CancelledError 要重新抛出
示例里这样写:
python
except asyncio.CancelledError:
print("slow_report: got cancel request")
raise
finally:
print("slow_report: cleanup")CancelledError 是 asyncio 用来通知协程“该停了”的异常。你可以在这里打日志、关连接、释放资源,但通常要 raise 回去。否则外层可能以为任务正常结束了。
finally 为什么会执行
取消不会把函数硬切掉。它更像一次异常:协程在等待点醒来时收到 CancelledError,然后正常执行 finally。
所以资源清理要放在 finally 里:
python
try:
...
finally:
writer.close()
await writer.wait_closed()小练习
- 把
timeout(0.2)改成timeout(2),确认任务会正常完成。 - 删除
except asyncio.CancelledError里的raise,你会发现外层不再打印main: timed out。这说明取消信号被里面吞掉了。 - 在
finally里加一行await asyncio.sleep(0.1),确认清理代码也可以包含异步等待。