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</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill8551" title="Claw Code Suite (Python-Only Edition)"><img src="https://img.php.cn/upload/skill/000/000/081/179212160094080.jpg" alt="Claw Code Suite (Python-Only Edition)" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill8551" title="Claw Code Suite (Python-Only Edition)" class="overflowclass">Claw Code Suite (Python-Only Edition)</a> <p class="overflowclass">仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...</p> </div> <a rel="nofollow" href="/xiazai/skill8551" title="Claw Code Suite (Python-Only Edition)" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div>
不能在普通函数或模块顶层直接用 await,会报 SyntaxError: 'await' outside async function
await 是语法关键字,只允许出现在 async def 定义的函数体内。想在脚本开头、交互式环境或同步逻辑里取协程返回值,得靠事件循环驱动。
- ✅ 在脚本中:用
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 对象,基本就不会掉坑里。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










