await位置错误会导致异步退化为同步:循环内await使请求串行,应改用asyncio.gather并发;非async函数中需用asyncio.run()或await调用;不可await非awaitable对象,如time.sleep或requests.get。

await位置不对不会直接报错,但会让异步代码退化成同步执行,完全失去并发优势。
await写在循环里导致串行执行
想并发请求 10 个 URL,却把 await 放在 for 循环内部,结果是逐个等待,总耗时 ≈ 所有请求时间之和。
- 错误写法:
for url in urls: data = await fetch(url)→ 每次都等上一个完成才发下一个 - 正确做法:先生成所有协程对象,再用
asyncio.gather()统一并发等待:results = await asyncio.gather(*[fetch(u) for u in urls]) - 注意:
gather()中传的是协程对象(fetch(u)),不是函数名(fetch);传错会报TypeError: an asyncio.Future, a coroutine or an awaitable is required
在非 async 函数里漏掉 await 或 asyncio.run()
常见于脚本顶层或 Flask/Django 视图中直接调用 async def 函数,比如写 result = my_coro(),它只返回一个 ,逻辑根本不执行。
- 现象:程序“没反应”、打印出
、或触发RuntimeWarning: coroutine 'xxx' was never awaited - 脚本顶层:必须用
asyncio.run(my_coro()) - 已运行事件循环的环境(如 FastAPI、Jupyter):改用
await my_coro(),不能用asyncio.run(),否则报RuntimeError: asyncio.run() cannot be called from a running event loop - 同步函数里要调异步逻辑:用
asyncio.get_event_loop().run_until_complete(my_coro())(Python 3.7+),或封装进线程池(asyncio.to_thread())
await了不该 await 的东西
比如对 CPU 密集型操作加 await,或误 await 一个普通函数、字符串、数字——这些都不是 awaitable,会直接报 TypeError。
- 典型错误:
await time.sleep(1)→time.sleep是同步阻塞,且不是协程,不能 await;应换await asyncio.sleep(1) - 更隐蔽的:
await requests.get(...)→requests是同步库,返回 Response 对象,不是协程;得换aiohttp或httpx.AsyncClient - 调试技巧:启用 asyncio 调试模式,
asyncio.run(main(), debug=True),能捕获长时间阻塞并警告
最易被忽略的是:await 本身不解决 CPU 瓶颈,只释放 I/O 等待期间的控制权。如果协程里混着大循环、正则匹配、JSON 解析等计算密集操作,整个事件循环会被卡住——这时候得用 loop.run_in_executor() 拆出去,而不是盲目加 await。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











