Python异步编程协程_事件循环解析【教程】

16次阅读

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

Python异步编程协程_事件循环解析【教程】

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() 更适合批量等待一组协程结果。

text=ZqhQzanResources