await后必须是可等待对象,否则报TypeError;协程函数调用返回coroutine对象,需await才执行;不可在普通函数或模块顶层直接使用await;并发需用asyncio.gather()或create_task()。

await 后面必须是可等待对象,否则报 TypeError: object X can't be used in 'await' expression
协程函数调用后返回的是一个 coroutine 对象,不是直接的值;直接 print 或赋值不会触发执行。常见错误是忘了加 await,或者误把普通函数、列表、None 丢给 await。
- ✅ 正确:调用协程函数后立刻
await,如await fetch_data() - ❌ 错误:写成
await fetch_data(没加括号,得到的是函数对象) - ❌ 错误:写成
await [1, 2]或await result(result 是已执行完的变量,不是协程) - ⚠️ 注意:
asyncio.run()内部会自动 await 顶层协程,但函数内部仍需显式 await 子协程
在 async def 函数里,return 的值就是 await 的返回值
协程函数的 return 不是“返回给函数”,而是“作为 await 表达式的求值结果”。这和同步函数一致,但容易因异步表象产生误解。
- 写
return 42,外面val = await my_coro()后,val就是42 - 不写
return,默认返回None,await结果也是None - 抛出异常时,
await会直接把异常冒泡出来,和同步 raise 行为一致 - 示例:
async def get_user_id(): return 1001 <p>user_id = await get_user_id() # user_id 是 int 类型,值为 1001
不能在普通函数或模块顶层直接用 await,会报 SyntaxError: 'await' outside async function
await 是语法关键字,只允许出现在 async def 定义的函数体内。想在脚本开头、交互式环境或同步逻辑里取协程返回值,得靠事件循环驱动。
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
立即学习“Python免费学习笔记(深入)”;
- ✅ 在脚本中:用
asyncio.run(main())包一层async入口函数 - ✅ 在 IPython/Jupyter 中:启用
%autoawait或用await coro(需已进入 async 模式) - ❌ 直接写
await asyncio.sleep(1)在 .py 文件最外层 —— 语法错误 - ⚠️ 注意:
asyncio.run()每次调用都会新建事件循环,不能在已有运行中的 loop 里重复调用(比如 Flask 或 FastAPI 的请求处理中)
并发多个协程时,await 单个会阻塞,要用 asyncio.gather() 或 asyncio.create_task()
连续写多个 await 是串行的,哪怕它们本身不互相依赖。想真正并发并收集返回值,必须把协程对象提前构造成任务,再统一 await。
- ❌ 串行写法(慢):
res1 = await fetch_a(); res2 = await fetch_b() - ✅ 并发写法(快):
res1, res2 = await asyncio.gather(fetch_a(), fetch_b()) - ✅ 更灵活写法:
task1 = asyncio.create_task(fetch_a()); task2 = asyncio.create_task(fetch_b()); res1 = await task1; res2 = await task2 - ⚠️
gather()遇到任一异常默认取消其余任务;如需“失败不中断”,加参数return_exceptions=True
实际写异步代码时,最常卡住的地方不是语法,而是混淆“协程对象”和“协程返回值”——前者是待执行的计划,后者是 await 执行完才有的东西。只要盯住每个 await 右边是不是一个真正的 coroutine 对象,基本就不会掉坑里。


















