async/await 是基于事件循环的用户态协程机制,通过await显式让出控制权,协程对象需await或asyncio.run启动,暂停时保存栈帧,底层复用生成器机制,事件循环负责i/o轮询与协程调度。

Python 的 async 与 await 不是线程或进程,而是一种用户态的协作式并发机制——协程(coroutine)。它的核心在于事件循环(event loop)驱动下的暂停与恢复,不依赖操作系统调度,而是由程序员用 await 显式让出控制权。
async 函数本质是“可等待对象工厂”
async def 定义的函数本身不是协程,而是一个协程函数;调用它返回的是一个协程对象(coroutine object),这个对象是可等待的(awaitable)。只有真正 await 它时,协程体才开始执行,并在遇到下一个 await 表达式时暂停,把控制权交还给事件循环。
- 协程对象不可直接调用(
coro()会报错),必须用await coro或asyncio.run(coro)启动 - 协程暂停时,不阻塞线程,只是保存当前栈帧(locals、指令指针等)到对象内部,后续可恢复
- 普通生成器用
yield暂停,协程用await暂停,但底层都基于 Python 的生成器机制(PEP 492 明确复用生成器框架)
await 触发“挂起-调度-恢复”三步动作
await 表达式不是简单等待,而是一套协作协议:
- 先检查右侧对象是否实现了
__await__方法(即是否为 awaitable),如asyncio.sleep()、其他协程、Future实例等 - 调用其
__await__()得到一个迭代器(通常是生成器),事件循环持续send(None)驱动它,直到抛出StopIteration - 若该 awaitable 尚未就绪(如网络未返回),它会向事件循环注册回调,并主动挂起当前协程;待 I/O 完成后,事件循环唤醒它继续执行
事件循环是协程的“中央调度器”
Python 运行时只有一个默认事件循环(主线程中可通过 asyncio.get_event_loop() 获取),它负责:轮询 I/O 状态(如 socket 是否可读)、管理挂起的协程队列、触发回调、分发恢复信号。你写的每个 await,最终都转化为事件循环的一次调度决策。
立即学习“Python免费学习笔记(深入)”;
-
asyncio.run()会创建新循环、运行协程、关闭循环——适合脚本入口 - 长期服务(如 web 服务器)通常手动维持一个循环,反复调用
loop.run_forever() - 协程之间不抢占,谁
await谁让出,没有锁或竞态问题,但共享变量仍需注意线程安全(因事件循环在单线程内运行)
协程与普通函数的关键区别在控制流语义
同步函数调用是“进→执行→出”,而 async 函数调用是“进→造协程→出”,真正执行发生在 await 时,且可能被多次中断和恢复:
- 函数内局部变量不会因挂起而丢失,它们绑定在协程对象的闭包中
- 每次
await后续代码的执行时间不确定,取决于被 await 对象何时就绪 - 不能在普通函数里
await,也不能在非async上下文中使用await(语法错误)









