Skip to content

实验 11:调试和易错点

最后看两个常见错误:创建 coroutine 但没等待;在 async def 里调用阻塞函数。

运行:

bash
python3 examples/asyncio_demos/11_debug_antipatterns.py

忘记 await

示例里故意写了:

python
forgotten_await()

这只创建 coroutine object,不会执行函数体。debug 模式下,你会看到类似“coroutine was never awaited”的警告。

改法:

python
await forgotten_await()

如果你想让它后台运行,也不要裸写,至少保存 Task:

python
task = asyncio.create_task(forgotten_await())

然后你要决定后面在哪里等待它、谁处理它的异常。

阻塞事件循环

示例里还故意写了:

python
time.sleep(0.2)

time.sleep() 会把当前线程睡住。事件循环也在这个线程里,所以别的 Task 没机会运行。

改法:

python
await asyncio.sleep(0.2)

如果你绕不开同步阻塞函数,可以临时放到线程里:

python
result = await asyncio.to_thread(blocking_function, arg)

这适合包一小段旧代码,不适合把大量 CPU 计算都塞进去。

打开 debug

示例入口是:

python
asyncio.run(main(), debug=True)

还设置了慢 callback 阈值:

python
loop.slow_callback_duration = 0.05

所以 time.sleep(0.2) 会被记录出来。线上不一定要一直开 debug,但开发和排查问题时很有用。

小练习

  1. forgotten_await() 改成 await forgotten_await(),确认警告消失。
  2. time.sleep(0.2) 改成 await asyncio.sleep(0.2),确认慢 callback 提示消失。
  3. 把一个普通同步函数放进 asyncio.to_thread(),观察事件循环是否还能处理别的 Task。

面向学习目的的 Python asyncio 中文教程与 mini_asyncio 教学运行时。