python 3.11 中 selectoreventloop 本身未提速,真实性能提升来自解释器底层优化:快速调用协议、字节码特化及栈帧分配改进,这些对所有事件循环策略均生效;显式使用 selectoreventloop 反易触发 macos kqueue 兼容性问题、windows 卡顿或错失 uvloop 的 2–4 倍 i/o 提升。

Python 3.11 的 SelectorEventLoop 并不“更高”——它只是更少被用到
直接说结论:SelectorEventLoop 在 Python 3.11 中没有变快,反而是被更激进地绕开了。真正提速的是解释器底层对 CALL_FUNCTION、LOAD_ATTR 等字节码的运行时特化,以及快速调用协议(Fast Call Protocol)带来的函数调用开销下降。如果你还在手动创建 asyncio.SelectorEventLoop() 或依赖它默认行为,反而可能错过 3.11 的真实优势。
为什么你看到的“SelectorEventLoop 更快”,其实是解释器在背后干活
所谓“SelectorEventLoop 效率提升”,本质是 Python 3.11 解释器优化了事件循环调度中高频出现的 Python 层操作,比如:
-
await表达式求值时的栈帧分配更紧凑,减少内存分配次数 - 协程对象的
send()调用不再走完整PyObject_Call流程,而是直传参数到寄存器级路径 -
asyncio.create_task()内部的函数调用(如包装coro.send)命中了特化指令CALL_FUNCTION_EX→CALL_FUNCTION_EX_FAST - 异常未抛出时,
try块几乎零开销;一旦raise,回溯构建也更轻量(PEP 657 支持精准列号,但构建成本更低)
这些优化对所有事件循环策略都生效,包括 SelectorEventLoop、ProactorEventLoop 和 uvloop。它们不改 I/O 多路复用机制,只让 Python 层调度更快。
SelectorEventLoop 在 3.11 下容易踩的坑
你如果显式使用 asyncio.SelectorEventLoop,反而可能触发退化路径:
- 在 macOS 12+ 上,
SelectorEventLoop仍依赖 kqueue,但 3.11 默认策略未自动 fallback,asyncio.get_event_loop()可能仍报RuntimeError: There is no current event loop in thread - Windows 下硬绑
SelectorEventLoop会卡顿,因为 select() 不支持管道/套接字重叠 I/O;此时WindowsProactorEventLoopPolicy才是正解 - Linux 下若已装
uvloop,却手动 new 一个SelectorEventLoop实例,等于主动放弃 2–4 倍 I/O 吞吐提升 -
SelectorEventLoop本身不支持asyncio.run()的自动关闭逻辑(3.11 引入的asyncio.Runner机制更健壮),容易残留未清理的 socket
该用什么?看平台和场景选策略,不是选 Loop 类型
真正影响性能的不是 SelectorEventLoop 本身,而是你是否让解释器有足够机会“热起来”:
- Linux 生产服务:装
uvloop,然后import uvloop; uvloop.install()—— 它兼容 3.11 特化,且替换的是底层事件循环,不干扰 Python 层优化 - macOS 开发机:设
asyncio.set_event_loop_policy(asyncio.SelectorEventLoopPolicy())仅用于兼容,别指望它变快;重点确保协程函数被反复调用(>53 次)以触发字节码特化 - Windows CLI 工具:用
WindowsProactorEventLoopPolicy,否则asyncio.sleep()或文件 I/O 可能阻塞主线程 - 短生命周期进程(如 AWS Lambda):特化根本来不及生效,与其纠结 Loop,不如把关键路径提前编译(
compile()+eval()预热)或改用threading+concurrent.futures
解释器不会告诉你哪条字节码被特化了,除非你加 -X showspeculation;也不会自动帮你选 Loop —— 这些都得你自己根据 OS 和部署模型决定。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











