应配置pytest显示RuntimeWarning以暴露漏await协程:在pyproject.toml中设python_warnings=["default::RuntimeWarning"],或命令行加-W default::RuntimeWarning;同时启用IDE检查和mypy插件强制校验。

pytest 默认忽略 RuntimeWarning
Python 自身在协程对象被垃圾回收时才触发 RuntimeWarning: coroutine 'xxx' was never awaited,但 pytest 启动时默认只捕获 DeprecationWarning 和 FutureWarning,RuntimeWarning 被直接丢弃。这不是 bug,是刻意设计:避免测试框架被非致命运行时提示干扰。
协程未 await 的真实后果
- 协程对象被创建后从未进入事件循环,等价于“写了但没发”
- HTTP 请求不会发出,数据库查询不会执行,定时任务不会启动
- 没有异常、没有返回值、没有 side effect,只有 GC 阶段终端一闪而过的警告
- 在 CI 环境里尤其危险:本地跑过,CI 偶发失败,排查时发现某次提交悄悄删掉了
await
必须显式启用警告才能暴露问题
靠 IDE 波浪线或 mypy 插件只能覆盖编辑时,运行时仍可能漏掉。真正起效的方式是让 pytest 主动透出警告:
- 推荐在
pyproject.toml中全局开启:python_warnings = ["default::RuntimeWarning"] - 命令行临时调试:
pytest -W default::RuntimeWarning - 注意:
-W参数不会自动透传给asyncio.run()内部或 fixture 子进程,必须配置在 pytest 层
asyncio.create_task() 和 asyncio.gather() 是合法消费
它们把协程包装成 Task 或 Future 并提交到当前事件循环,不触发警告;但以下写法会踩坑:
-
list(map(my_async_func, items))→ 生成一堆未 await 协程对象 - 正确写法:
await asyncio.gather(*[my_async_func(x) for x in items]) -
asyncio.create_task()必须确保 task 最终被await或asyncio.wait()消费,否则仍会警告
Coroutine is not awaited、VS Code 的 Pylance reportUnusedCoroutine)比运行时警告更早、更准。


















