Python asyncio 事件循环的底层执行机制

2次阅读

asyncio.run() 只能调用一次,因其每次创建并关闭新事件循环,重复调用会报 runtimeerror;它专为脚本入口设计,非循环复用接口

Python asyncio 事件循环的底层执行机制

asyncio.run() 为什么只能调用一次?

因为 asyncio.run() 内部会创建新事件循环、运行完就关闭它,再调用就会触发 RuntimeError: asyncio.run() cannot be called from a running Event loop。这不是 bug,是设计约束——它专为“脚本入口”场景服务,不是循环复用接口。

  • 想多次执行异步逻辑?直接用 asyncio.get_event_loop().run_until_complete()python 3.7+ 推荐改用 asyncio.run() 的替代方案:手动管理循环)
  • 在已运行的协程里启动新任务?用 asyncio.create_task()loop.create_task(),别碰 run_until_complete
  • jupyter 或 REPL 里调试时容易误调两次 asyncio.run(),报错后得重启 kernel 才能恢复

事件循环怎么实际调度 awaitable 对象

不是“一遇到 await 就切走”,而是 await 表达式返回一个 awaitable 对象(比如 coroutineFuture、实现了 __await__ 的对象),事件循环把它注册进内部的 ready 队列或等待队列,然后根据状态(如 I/O 完成、超时、被 cancel)决定何时恢复执行。

  • await asyncio.sleep(0) 强制让出控制权,相当于“插入一个立即就绪的任务”,常用于避免长协程饿死其他任务
  • 纯 CPU 密集型操作(比如大数组计算)不会自动让出,必须手动加 await asyncio.sleep(0) 或拆成小块 + asyncio.to_thread()(3.9+)
  • 底层依赖系统级通知机制:linuxepollmacoskqueuewindowsIOCP;这些不暴露给用户,但影响并发上限和延迟敏感度

自定义事件循环(比如 uvloop)要替换哪些地方?

替换的是事件循环策略(asyncio.AbstractEventLoopPolicy)的默认实现,不是直接换掉 asyncio.run() 本身。uvloop 提供的是更快的 loop 实例,但所有高层 API(create_taskgather 等)行为不变。

  • 生效方式只有两种:asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())(全局策略),或 uvloop.new_event_loop() + asyncio.set_event_loop()(手动设当前线程 loop)
  • 不能在 asyncio.run() 已启动后替换,否则报 RuntimeError: Cannot run the event loop while another loop is running
  • uvloop 不支持 Windows,且部分调试工具(如 asyncio.debug 模式)可能失效;生产环境提速明显,开发期建议保留默认 loop 方便排查

loop.run_forever() 和 loop.run_until_complete() 的关键区别

前者是“永动机”,除非你手动调 loop.stop(),否则不会退出;后者是“跑完指定协程就停”,适合单次任务。两者都要求 loop 处于未运行状态,重复调用会报 RuntimeError: this event loop is already running

立即学习Python免费学习笔记(深入)”;

  • run_until_complete()asyncio.run() 底层实际调用的方法,它会在结束前自动 close() loop —— 所以你不能再对这个 loop 做任何事
  • run_forever() 常用于服务器主循环(比如 asyncio.start_server() 启动后),需要自己管理 shutdown:监听信号、取消 pending task、调 loop.stop()loop.close()
  • 忘记调 loop.close() 会导致资源泄漏(比如 socket fd 未释放),尤其在短生命周期脚本中容易被忽略

事情说清了就结束。真正难的不是理解调度逻辑,而是判断什么时候该让出、什么时候该换 loop、以及怎么在 close 之前安全清理所有 task。

text=ZqhQzanResources