如何安全地取消Python协程的_task.cancel()并处理CancelledError异常及资源清理?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1008个文字,预计阅读时间需要5分钟。
由于`asyncio.Task.cancel()`并非温和提示取消,而是为协同程序打上已取消标记,并在下一个`await`点主动触发`CancelledError`——这是asyncio的协作式取消机制,而非强制中断。
协同程序必须自己响应这个异常,否则即使逻辑基本正常也不会退出。
常见错误现象:task.cancel() 调用了,但 finally 没执行、async with 没退出、socket 没 close、文件没 flush。
- 协程里没写
try/except CancelledError或没用finally - 在
await之前就卡死(比如死循环、CPU 密集型计算),永远等不到抛异常的时机 - 用了
loop.run_in_executor调用阻塞函数,取消对线程内执行无影响
如何安全退出并确保资源清理?
核心原则:把清理逻辑放在 finally 块里,或用 async with / async for 自动管理。Cancel 之后,协程会在下一个可挂起点被中断,然后流程自然进入 finally。
使用场景:HTTP 客户端连接、数据库连接池、临时文件写入、长轮询任务。
本文共计1008个文字,预计阅读时间需要5分钟。
由于`asyncio.Task.cancel()`并非温和提示取消,而是为协同程序打上已取消标记,并在下一个`await`点主动触发`CancelledError`——这是asyncio的协作式取消机制,而非强制中断。
协同程序必须自己响应这个异常,否则即使逻辑基本正常也不会退出。
常见错误现象:task.cancel() 调用了,但 finally 没执行、async with 没退出、socket 没 close、文件没 flush。
- 协程里没写
try/except CancelledError或没用finally - 在
await之前就卡死(比如死循环、CPU 密集型计算),永远等不到抛异常的时机 - 用了
loop.run_in_executor调用阻塞函数,取消对线程内执行无影响
如何安全退出并确保资源清理?
核心原则:把清理逻辑放在 finally 块里,或用 async with / async for 自动管理。Cancel 之后,协程会在下一个可挂起点被中断,然后流程自然进入 finally。
使用场景:HTTP 客户端连接、数据库连接池、临时文件写入、长轮询任务。

