Python异步编程的核心是协程与事件循环配合:协程需由事件循环调度执行,asyncio.run()是推荐的启动方式,await用于让出控制权,create_task()或gather()实现并发。

Python异步编程的核心是协程(coroutine)与事件循环(event loop)的配合。协程本身不自动运行,必须由事件循环调度执行;而事件循环是异步程序的“心脏”,负责监听I/O事件、分发任务、驱动协程推进。
协程不是线程,也不自动并发
定义一个 async def 函数只是创建了一个协程对象,它不会立即执行:
async def fetch_data():
print("start")
await asyncio.sleep(1)
print("done")
coro = fetch_data() # 此时什么都没发生
协程对象需要被“提交”给事件循环才能运行。直接调用 coro.send(None) 或手动驱动会绕过事件循环,失去异步能力,也容易出错。
事件循环是唯一调度中心
Python 3.7+ 推荐使用 asyncio.run() 启动主协程,它会自动创建并管理一个事件循环:
立即学习“Python免费学习笔记(深入)”;
-
asyncio.run(main()):最简方式,适合脚本和主入口,运行结束后自动关闭循环 -
asyncio.get_event_loop():获取当前线程的默认循环(已弃用,不推荐) -
asyncio.new_event_loop()+set_event_loop():用于多线程场景,需自行管理生命周期
注意:一个线程只能有一个运行中的事件循环;多次调用 run() 会报错“event loop is running”。
await 的本质是让出控制权
await 表达式不是等待,而是向事件循环发出信号:“我暂时不干活了,请去执行别的协程”。事件循环会在被 await 的对象(如 asyncio.sleep()、aiohttp.get())准备好后,恢复该协程继续执行。
- 只能在
async def函数中使用await - 被 await 的对象必须是 awaitable:协程对象、带
__await__方法的对象、或Future实例 -
await asyncio.sleep(0)是主动让出一次调度权的常用技巧
并发靠 asyncio.create_task() 或 gather()
单个 await coro 是顺序执行;要真正并发,需把多个协程包装为任务并同时提交:
async def main():
task1 = asyncio.create_task(fetch_data("A"))
task2 = asyncio.create_task(fetch_data("B"))
await task1
await task2 # 等两个都完成
或更简洁地:
await asyncio.gather(fetch_data("A"), fetch_data("B"))
create_task() 立即调度协程,适合需要提前启动、中间有逻辑判断、或需取消任务的场景;gather() 更适合批量等待一组协程结果。











