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个全在等它返回。
- 替换
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里的逻辑压根没执行。
SkillSub Pro - Python 题解与代码注释双功能技能功能概述SkillSub Pro - Python 题解与代码注释双功能技能是一项面向实际任务的技能,主要用于SkillSub Pro 是一个 Python 题解生成与代码注释的 双功能合体技能 ,专为学生、算法学习者和开发者设计;✅ 一个技能,两种用途 :;核心要点📝 题解模式 :输入题目/题号,自动生成完整 Python 题解(含详细注释、解题思路、复杂度分析);💬 注释模式 :输入 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"),比猜强得多。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










