跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

Python异步IO为什么不起作用_检查是否漏写await或混用同步代码

async函数未加await调用不会执行,仅返回协程对象;必须在async函数内用await调用,顶层需用asyncio.run()启动;混用同步阻塞操作会卡住事件循环。 async函数里没加await,调用就变成同步执行 Python的
async
函数本身不触发异步行为,只是返回一个
coroutine
对象。如果你直接调用
fetch_data()
却没写
await fetch_data()
,它根本不会运行,也不会报错——只是静默地丢弃协程对象。 常见错误现象:
RuntimeWarning: coroutine 'fetch_data' was never awaited
(但这个警告默认可能被忽略,尤其在Jupyter或某些IDE中)。 检查所有
async
函数调用点:必须出现在
async
函数内,且前面有
await
顶层代码不能直接
await
,得用
asyncio.run(main())
启动 别把协程对象赋值给变量却不
await
,比如
coro = fetch_data(); result = coro
——这等于什么都没做 混用同步阻塞调用(如time.sleep、requests.get)导致整个event loop卡住 asyncio event loop是单线程的,一旦执行了同步阻塞操作(比如
time.sleep(5)
或
requests.get()
),整个协程调度就停摆,其他任务无法并发执行。 使用场景:你想并发请求10个API,但其中某个用了
requests.get
,结果其余9个全在等它返回。 立即学习 “ Python免费学习笔记(深入) ”; 替换
time.sleep
→
await asyncio.sleep
替换
requests.get
→ 用
aiohttp.ClientSession
或
httpx.AsyncClient
已有同步库又没法换?用
loop.run_in_executor
把阻塞调用扔到线程池,但要注意开销和上下文丢失 忘记在async函数里用await调用另一个async函数 这是最隐蔽的坑:你写了两个
async
函数,A调用B,但在A里写了
B()
而不是
await B()
。结果B的协程被创建又丢弃,A继续往下跑,B里的逻辑压根没执行。 Python 3.14.3 微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。 下载 示例:
async def load_user(): return await db_query()
,如果误写成
db_query()
(没await),
load_user
会立即返回
None
,且
db_query
完全没跑。 逐行检查所有
async
函数内部的函数调用,凡返回
coroutine
对象的,必须
await
用IDE的类型提示(如标注返回
Awaitable[T]
)或mypy插件辅助识别
print(type(some_call()))
临时调试:如果是 ,那就漏await了 await在非async函数里使用,语法直接报错
await
只能出现在
async def
定义的函数体内。如果写在普通
def
函数、模块顶层、或者
if
分支里但外层不是async函数,Python会立刻抛出
SyntaxError: invalid syntax
。 容易被忽略的地方:条件分支嵌套深、重构时把一段逻辑剪切出来忘了补
async
、或者误以为装饰器(如
@router.get
)自动提供了async上下文。 确认当前函数是否以
async def
开头,不是
def
FastAPI/Starlette等框架中,路由处理函数必须是
async def
,否则await无效或报错 交互式环境(如IPython)不支持顶层
await
,得用
await coro
前先确保在async函数里,或用
asyncio.run(coro)
真正卡住async程序的,往往不是语法错误,而是“看起来在跑,其实没并发”——比如漏await、混进一个
time.sleep
、或者用
requests
发了10个串行请求还自以为是异步。多打一行
print("start") / print("done")
,比猜强得多。

相关文章