
asyncio.run() 会在主协程结束后自动取消所有未完成的后台任务,并触发 CancelledError;但为确保资源清理和逻辑完整性,显式管理任务生命周期仍是推荐的最佳实践。
`asyncio.run()` 会在主协程结束后自动取消所有未完成的后台任务,并触发 `cancellederror`;但为确保资源清理和逻辑完整性,显式管理任务生命周期仍是推荐的最佳实践。
在使用 asyncio.create_task() 启动后台异步任务时,一个常见误区是认为“只要主程序结束,任务就会静默退出”。实际上,asyncio.run() 在事件循环关闭前会主动取消所有仍在运行的 Task 实例,并等待它们响应取消信号(即抛出或捕获 asyncio.CancelledError)。这一机制保障了基本的资源回收,但并不等同于“优雅关闭”——尤其当任务持有文件句柄、网络连接、数据库事务或需执行清理逻辑时,仅依赖自动取消可能导致状态不一致或资源泄漏。
以下是一个验证自动取消行为的改进示例:
import asyncio
import random
import time
async def forever_while_loop_task():
try:
while True:
sleep_seconds = random.randint(5, 30)
print(f"→ sleeping for {sleep_seconds} seconds")
await asyncio.sleep(sleep_seconds)
print("→ looping")
except asyncio.CancelledError:
print("⚠️ The forever_while_loop_task was cancelled — performing cleanup...")
# ✅ 此处可安全释放资源:关闭连接、提交/回滚事务、写入日志等
await asyncio.sleep(0.1) # 模拟轻量清理操作
print("✅ Cleanup completed.")
raise # 必须重新抛出,否则取消信号被吞没
async def main():
start = time.monotonic()
task = asyncio.create_task(forever_while_loop_task())
await asyncio.sleep(20)
print(f"✔️ ok done with program, took {time.monotonic() - start:.2f}s")
# ✅ 推荐:显式取消并等待完成,确保清理逻辑执行
if not task.done():
task.cancel()
try:
await task # 等待任务响应取消并完成 cleanup
except asyncio.CancelledError:
pass # 预期行为:任务已处理取消
if __name__ == "__main__":
asyncio.run(main())
? 关键点说明:
macOS UI 自动化技能包 —— 用 Python 控制你的 Mac下载让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- task.cancel() 发送取消请求,但不会立即终止协程;它只是将 CancelledError 注入任务的下一次 await 点;
- await task 是必要的:它让主协程等待任务真正退出(包括 finally 块或 except CancelledError 中的清理代码);
- 若忽略 await task,asyncio.run() 仍会尝试取消,但可能跳过清理阶段(尤其在任务处于 CPU 密集型非 await 状态时),且无法保证清理顺序与超时控制。
? 最佳实践总结:
- ✅ 始终在退出前显式 cancel + await 重要后台任务,尤其是涉及 I/O、状态变更或外部依赖的任务;
- ✅ 在任务内部用 try/except CancelledError 或 finally 块封装清理逻辑,切勿静默吞掉 CancelledError;
- ✅ 对多个任务,优先考虑 asyncio.TaskGroup(Python 3.11+):它提供结构化并发与自动传播取消;
- ⚠️ 避免依赖 asyncio.run() 的隐式取消作为唯一保障——它不提供超时、重试或错误分类能力,也不适用于长期服务(如 Web 服务器)的平滑重启场景。
通过主动管理任务生命周期,你不仅能写出更健壮的异步程序,还能显著提升可观测性与可维护性。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











