
本文详解 Python 中 async/await 的本质——它实现的是协程级的协作式并发,而非自动并行;关键在于 await 点是否让出控制权,以及被调用函数是否真正异步(如使用 asyncio.sleep),而非仅标记为 async def。
本文详解 python 中 `async`/`await` 的本质——它实现的是协程级的**协作式并发**,而非自动并行;关键在于 `await` 点是否让出控制权,以及被调用函数是否真正异步(如使用 `asyncio.sleep`),而非仅标记为 `async def`。
在机器学习服务等 I/O 密集型场景中,合理运用 asyncio 能显著提升吞吐量。但一个常见误区是:仅将函数声明为 async def 并不使其“自动异步”。真正的异步执行依赖两个必要条件:
- 函数内部必须包含可挂起的 await 表达式(如 await asyncio.sleep()、await aiohttp.get());
- 并发调度需通过 asyncio.gather()、asyncio.create_task() 等显式组合协程,而非顺序 await。
以您提供的三段代码为例:
同步版本(1):predict() 使用 time.sleep(3) —— 这是阻塞式系统调用,会冻结整个事件循环,apply_business_logic() 必须等待其完成,总耗时约 3 + ε 秒。
伪异步版本(2):虽然 predict() 和 apply_business_logic() 均标记为 async def,但后者未含任何 await,仍是同步执行。await predict(x) 执行时,事件循环进入 predict 协程并等待 asyncio.sleep(3) 完成;随后 await apply_business_logic(x) 才开始执行——二者串行等待,总耗时仍接近 3 秒(predict 耗时主导),并未并发。
A Python CLI skill for Cutout.Pro visual APIs — background removal, face cutout, and photo enhancement. Supports file upload & image URL input.下载调用 Cutout.Pro 视觉处理 API 进行背景移除、人像抠图和照片增强,支持文件上传与图片 URL 输入。
真正异步版本(3):asyncio.gather(predict(x), apply_business_logic(x)) 同时启动两个协程。predict 在 await asyncio.sleep(3) 时主动让出控制权,事件循环立即调度 apply_business_logic(其内部无 await,瞬间完成)。最终总耗时由最慢任务决定(≈3 秒),但 CPU 利用率更高,且为后续扩展 I/O 操作(如模型推理 API 调用)预留了并发能力。
✅ 正确实践的关键代码模式:
import asyncio
async def predict(x: list[int]) -> float:
await asyncio.sleep(3) # ✅ 真正可挂起的异步等待
return sum(x) / len(x)
async def apply_business_logic(x: list[int]) -> int:
# ⚠️ 若此处有耗时同步计算(如复杂规则引擎),应包装为线程执行
loop = asyncio.get_running_loop()
result = await loop.run_in_executor(None, lambda: sum(x) ** 2)
print(">> finish `apply_business_logic` function!")
return result
async def main(x: list[int]) -> float:
x = preprocess(x) # 同步预处理,无需 await
# ✅ 并发执行独立任务
pred_result, logic_result = await asyncio.gather(
predict(x),
apply_business_logic(x)
)
return 0.7 * pred_result + 0.3 * logic_result
# 运行入口(推荐 asyncio.run,自动管理事件循环)
if __name__ == "__main__":
x = list(range(100))
resp = asyncio.run(main(x))
print("resp >>", resp)
⚠️ 重要注意事项:
- asyncio 无法加速纯 CPU 密集型同步计算(如 sum(x)**2)。若业务逻辑含大量 CPU 工作,应结合 loop.run_in_executor() 将其卸载至线程池,避免阻塞事件循环;
- 所有 await 表达式必须作用于可等待对象(Awaitable),包括协程、asyncio.Future、实现了 __await__ 的对象;
- 避免在 async def 函数中混用 time.sleep()、requests.get() 等同步阻塞调用——它们会退化为同步行为,丧失并发优势。
总结:async/await 是一套协作式并发协议,其效能取决于是否在合理位置插入 await 让出控制权,以及被等待的操作本身是否支持非阻塞。理解这一点,才能在 ML 服务、API 网关等场景中真正释放异步编程的性能红利。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










