async/await下资源释放的核心原则是无论操作成功、失败或取消,清理逻辑都必须执行;应使用try-finally或async with确保清理,设计幂等清理函数,主动响应取消,并在服务退出时统一协调带超时的全局清理。

在 async/await 模式下,资源释放的核心原则是:**无论操作成功、失败还是被取消,清理逻辑都必须执行**。靠“写完就关”或“最后手动调用 close”极易遗漏,尤其在异常或中断场景下。真正可靠的做法是把清理嵌入执行流程本身。
用 try-finally 包裹异步操作
这是最基础也最可靠的模式。关键点在于:
- 资源获取放在 try 块外(否则 finally 无法访问)
- 所有清理操作(如
await conn.aclose()、await file.close())写在 finally 中,并加上 await - 清理函数设计为幂等——重复调用不报错,避免 cancel 后又进 finally 导致二次关闭出错
优先使用 async with 管理生命周期
只要资源类实现了 __aenter__ 和 __aexit__,就能用 async with 自动处理。它本质就是语法糖,背后仍是 try-finally 逻辑,但更简洁、不易出错:
-
__aenter__负责异步初始化(比如建连、加锁) -
__aexit__在退出时自动触发,接收异常信息,可区分正常退出与异常中断 - 标准库如
aiohttp.ClientSession、第三方库如aiomysql都支持该协议
主动响应任务取消
当 task.cancel() 被调用,协程会在下一个 await 处收到 CancelledError。此时需:
- 在
try块中await长耗时操作 - 用
except asyncio.CancelledError捕获,执行必要清理(如释放锁、回滚事务) - 清理后 重新 raise,确保上层能感知取消状态
- 别依赖 except 就够了——仍要在 finally 补一层保障,防止捕获后漏掉清理
服务退出阶段统一协调清理
单个函数的清理不够,整个应用关闭时需全局统筹:
- 监听
SIGTERM或SIGINT信号,启动关闭流程 - 先拒绝新请求,再等待运行中协程自然结束(或设超时)
- 按依赖顺序释放:比如先停工作协程,再关数据库连接,最后释放文件句柄或事件监听器
- 用
asyncio.wait_for(..., timeout=5.0)给每一步清理加超时,避免卡死

















