当前位置: 首页 > news >正文

[Python3高阶编程] - 异步编程深度学习指南一(补充2):深入理解关键词 await

一、await的核心作用

await的作用是:暂停当前协程的执行,将控制权交还给事件循环(event loop),直到等待的对象“完成”后再恢复执行,并获取其结果。

类比理解:

想象你在排队买咖啡:

  • step1. 你点单后(发起 I/O 请求),店员说“稍等,正在做”
  • step2. 你不会傻站着(阻塞),而是去刷手机(事件循环执行其他任务)
  • step3. 咖啡好了(I/O 完成),店员叫你(事件循环唤醒你)
  • step4. 你拿到咖啡(获取结果),继续走路

await就是那个“点单(step1) + 等待叫号(step3)”的动作。


二、await后面能接什么?——必须是 “awaitable” 对象

await不能接任意对象,只能接实现了__await__方法的对象,即“awaitable”

Python 中主要有三类 awaitable 对象:

类型说明示例
1. 协程(Coroutine)async def定义的函数调用返回fetch_data()
2. Task对协程的封装,由事件循环调度asyncio.create_task(fetch_data())
3. Future底层异步操作的占位符(通常由库内部使用)loop.run_in_executor(...)返回

重点

  • async def func(): ...定义的是协程函数
  • 调用func()返回的是协程对象(coroutine object)
  • 这个协程对象就是 awaitable 的!

三、详细示例解析

示例 1:await协程对象(最常见)

import asyncio async def fetch_data(): await asyncio.sleep(1) # 模拟异步 I/O return "Data from server" async def main(): # fetch_data() 返回一个协程对象 coro = fetch_data() print(type(coro)) # <class 'coroutine'> # await 它,会执行并返回结果 result = await coro print(result) # "Data from server" asyncio.run(main())

过程

  1. fetch_data()创建协程对象(未执行!)
  2. await coro→ 事件循环开始执行该协程
  3. 遇到await asyncio.sleep(1)→ 暂停,让出控制权
  4. 1 秒后,sleep 完成 → 恢复执行 → 返回"Data from server"
  5. result得到该值

示例 2:awaitTask(推荐用于并发)

async def main(): # 创建 Task(立即被调度) task = asyncio.create_task(fetch_data()) # 可以做其他事... print("Doing other work...") # 等待 Task 完成并获取结果 result = await task print(result)

💡Task vs 协程对象

  • 直接await fetch_data():顺序执行
  • task = create_task(...); await task:可与其他任务并发(虽然这里只等一个)

示例 3:await多个任务(并发)

async def main(): # 同时启动多个任务 task1 = asyncio.create_task(fetch_data()) task2 = asyncio.create_task(fetch_data()) # 等待全部完成 r1 = await task1 r2 = await task2 # 或 r1, r2 = await asyncio.gather(task1, task2)

四、await如何返回结果?

✅ 规则很简单:

await some_awaitable的值 = 该 awaitable 最终return的值

async def add(a, b): return a + b # ← 返回值 async def main(): result = await add(2, 3) # result = 5

❌ 如果协程抛出异常:

async def bad(): raise ValueError("Oops!") async def main(): try: await bad() except ValueError as e: print(e) # "Oops!" —— 异常会被 re-raise

⚠️重要await不仅传递结果,也传递异常!


五、常见误区澄清

❌ 误区 1:await只能接async def函数调用

✅ 正确:可以接任何 awaitable(Task、Future、自定义 awaitable)

❌ 误区 2:await func()会“启动”函数

✅ 正确:func()已经创建了协程对象,await是“执行并等待完成”

❌ 误区 3:await是“阻塞”的

✅ 正确:对当前协程是“暂停”,但对整个程序是非阻塞的
事件循环会去执行其他协程。


六、自定义 awaitable 对象(高级)

你也可以让自己的类支持await

class MyAwaitable: def __await__(self): # 必须返回一个 generator 或 awaitable yield from asyncio.sleep(1).__await__() return "Custom result" async def main(): result = await MyAwaitable() print(result) # "Custom result"

💡 实际开发中极少需要,但理解这点有助于掌握原理。


七、总结:await的本质

问题答案
await的作用?暂停当前协程,交出控制权,等待异步操作完成
后面接什么?必须是awaitable 对象(协程、Task、Future)
如何返回结果?返回该 awaitable 的return值(或抛出异常)
是否阻塞?不阻塞事件循环,只暂停当前协程
必须在async def中使用?✅ 是的!否则语法错误

💡终极口诀
await等的是‘未来’,拿的是‘结果’,放的是‘控制权’。”

掌握这一点,你就真正理解了 Python 异步编程的精髓!

http://www.jsqmd.com/news/568829/

相关文章:

  • 2026 AI提效工具全景图:职场人、创作者、开发者如何选对工具?
  • 4个步骤掌握LatentSync:从入门到精通AI视频处理核心功能
  • [D2RML多开解决方案]:突破暗黑2重制版多账号管理效率瓶颈的创新实践
  • Google 地图事件:探索、挑战与未来展望
  • FPGA实现TCP/IP服务器端通信的那些事儿
  • 新手必看:在快马生成的代码中轻松理解rate limit exceeded
  • 保姆级教程:用Python和FastMCP为Qoder打造一个ROS2节点探测器
  • 基于GADF-CNN-GOSO-LSSVM的齿轮箱故障诊断方法探索
  • 别再只数步数了!深入聊聊ADXL345计步算法里的‘动态阈值’与‘最活跃轴’
  • 宝塔面板+Docker部署AList私人网盘:从零到域名绑定的完整指南
  • 谁应该拥有 MCP:平台团队、业务团队,还是 AI 团队?
  • 快速原型实践:基于快马平台,五分钟创建openclaw配置模型的抓取仿真原型
  • 数据分析相关面试题汇总
  • Comsol仿真无损检测时产生的兰姆波 导波在宽度和厚度有限的钢板中传播 板上有一条裂隙,尺寸...
  • Pixel Language Portal应用场景:开源AI模型Hub多语种模型卡自动维护系统
  • 告别纯Verilog手搓!用Vivado HLS快速搭建你的第一个CNN加速器(ZYNQ平台实战)
  • 手把手教你解决Vivado的ODDR_has_invalid_load报错:从RGMII设计实例到ILA采样的正确姿势
  • 从零开始:draw.io桌面版完全指南,释放你的离线绘图超能力
  • matlab 变步长NLMS仿真,该文件有文中的几种仿真,包括基本的仿真,信道突变下的追踪性能...
  • 2026年揭秘:国内高压电磁阀制造厂谁更值得信赖?
  • Qwen3.5-2B镜像免配置部署:开箱即用WebUI(7860端口)快速上手教程
  • Shell 变量
  • Unity Addressables远程资源加载避坑指南:从Local到Remote的路径设置全解析
  • WAN2.2文生视频开源镜像快速上手:ComfyUI界面操作+SDXL Prompt Styler详解
  • 安规设计规范-3(如何计算电气间隙和爬电距离)
  • 【限时解密】Oracle JVM团队内部流出的虚拟线程配置白皮书(含27个真实故障案例+对应jstack/jcmd诊断命令集)
  • FPGA时序优化实战:Xilinx IDELAYE2在高速信号处理中的5种应用场景
  • 从LaMa到BrushNet:盘点图像修复(Inpainting)领域的关键模型与实战数据集
  • 为什么OpenJDK 21+ Vector API让NumPy Java绑定项目集体停更?揭秘JVM原生向量化不可逆趋势
  • (20)ArcGIS Pro 矢量处理实战:合并、要素融合与消除全流程详解