Python协程异常不立即抛出,而是挂起至await时才浮现;未await的协程异常被静默丢弃;await链中异常逐层传递;取消操作引发CancelledError,需显式处理。

Python 协程中异常的传播和处理,与普通函数不同:它不是立即抛出,而是被“挂起”并延迟到 await 表达式求值时才真正浮现。理解这一机制,是写出健壮异步代码的关键。
协程异常不会自动向上冒泡
一个协程内部发生异常(如 ValueError),并不会像同步函数那样立刻中断调用栈。它会被封装进协程对象的状态中,直到该协程被 await —— 此时异常才被重新抛出到 awaiter 所在的上下文中。
例如:
async def bad_coro():
raise RuntimeError("oops")
async def main():
coro = bad_coro() # ✅ 不会报错,只是创建协程对象
await coro # ❌ 这里才真正抛出 RuntimeError
未 await 的协程异常会被静默丢弃
如果协程对象被创建后从未被 await,其内部异常将永远不会触发,也不会警告。这容易导致逻辑错误被掩盖。
立即学习“Python免费学习笔记(深入)”;
公文是政府与企事业单位处理公务和行政管理工作的重要工具,在各级行政单位中,`办公`的一个重要内容就是办理和制发文件,即`办文`,办文是每个行政管理单位大量日常的工作。借助新的网络信息技术对公文进行高效有序的电子化处理,是办公自动化建设的重要组成部分,也是关系到电子化办公系统建设全局的基础性工程。
- 避免直接丢弃协程对象,比如写成
bad_coro()而不 await 或赋值给变量 - 使用
asyncio.create_task()启动协程时,异常仍会传播到 task 对象;但若 task 未被await或task.exception()检查,也会被忽略 - 启用
asyncio.get_event_loop().set_exception_handler()可捕获未处理的 task 异常,用于调试
异常可在 await 链中逐层传递
多个 await 嵌套时,异常会沿调用链向上传播,行为类似同步函数的异常冒泡:
async def inner():
raise KeyError("missing")
async def middle():
await inner() # 异常在此处捕获并继续上抛
async def outer():
try:
await middle()
except KeyError as e:
print("caught:", e) # ✅ 这里能捕获
注意:不能在非 await 上下文中用 try/except 捕获协程内部异常——必须 await 后才能进入异常处理逻辑。
取消操作会引发 CancelledError
调用 task.cancel() 或超时触发取消时,协程会在下一个 await 点收到 asyncio.CancelledError(继承自 BaseException)。它不会被普通 except Exception: 捕获,需显式处理或使用 except BaseException:(不推荐)。
- 推荐在关键清理逻辑中使用
try/finally或async with确保执行 - 可在协程内用
if asyncio.current_task().cancelled():主动检查是否被取消 - 调用
await asyncio.shield(some_coro)可防止内部协程被外部取消影响









