asyncio.run(main(), debug=True)是最直接启用debug模式的方式,它自动开启事件循环调试、暴露未await协程、未关闭任务等异常,并输出slow callback等关键警告。

asyncio.run() 启用 debug=True 参数最直接
Python 3.7+ 的 asyncio.run() 支持直接传入 debug=True,这是开启 asyncio 调试模式最简单、最推荐的方式。它会自动启用事件循环的调试开关,并在出现慢回调、未完成任务、未处理异常等场景时输出警告或错误信息。
- 仅需改一行:把
asyncio.run(main())换成asyncio.run(main(), debug=True) - 无需手动获取或配置事件循环,避免因多次调用
asyncio.get_event_loop()导致的RuntimeError: no running event loop - 底层等效于设置
loop.set_debug(True)+ 启用asyncio.get_event_loop().slow_callback_duration = 0.1(默认阈值 0.1 秒)
手动设置 loop.set_debug(True) 需配合 get_running_loop()
如果你绕过 asyncio.run()、自己创建并运行事件循环(比如用 loop.run_until_complete()),就必须显式调用 set_debug(True),且必须在事件循环启动前设置——否则无效。
- 错误写法:
loop = asyncio.new_event_loop()→loop.run_until_complete(main())→loop.set_debug(True)(太晚,不起作用) - 正确顺序:
loop = asyncio.new_event_loop()→loop.set_debug(True)→loop.run_until_complete(main()) - 在协程内部不能用
asyncio.get_event_loop()获取正在运行的 loop 来设 debug;应使用asyncio.get_running_loop(),但注意它只在协程中可用,且设 debug 对当前 loop 有效,但无法改变已启动的 slow callback 检测阈值
识别卡顿的关键日志:slow callback 和 unhandled exception
开启 debug 后,真正能暴露卡顿问题的日志通常有两种:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
-
Executing <...> took—— 表明某个回调(比如s, which exceeds the configured threshold of s loop.call_soon()注册的函数、asyncio.sleep(0)后的调度点)执行超时,N 远大于 T(默认 0.1)说明有同步阻塞操作混入 -
Task was destroyed but it is pending!或Unclosed client session—— 不一定直接导致卡顿,但反映资源未清理、任务被粗暴取消,可能掩盖真实瓶颈 - 注意:这些日志默认输出到 stderr,若你重定向了日志,需确保
warnings和asyncio日志级别没被过滤(如 logging.basicConfig(level=logging.DEBUG) 可见)
常见卡顿源头与对应排查动作
debug 模式只报现象,不自动定位根源。看到 slow callback 后,要立刻检查以下几类代码:
- 同步 I/O:比如在协程里直接调用
requests.get()、open()、time.sleep()—— 必须换成aiohttp.ClientSession、aiopath或asyncio.sleep() - CPU 密集型操作:如大数组计算、JSON 解析、正则匹配 —— 应用
loop.run_in_executor()托管到线程池 - 第三方库未适配 async:某些 ORM(如早期 SQLAlchemy)或 SDK 默认是同步的,需确认是否提供 async 版本或配套驱动(如
asyncpg而非psycopg2) - 死锁式 await:比如两个协程互相
await对方的asyncio.Event或asyncio.Lock,debug 不会直接提示,但会导致事件循环长时间无进展,此时需结合asyncio.all_tasks()查看哪些 task 卡在WAITING状态
debug 模式本身有开销,尤其在高频回调场景下会显著拖慢性能,上线前务必关闭 debug=True;更隐蔽的卡顿(比如 sub-millisecond 级别抖动)需要配合 tracemalloc 或 py-spy record 进一步下钻。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










