Python 3.11 提升异步IO效率需规避uvloop双核退化、禁用ASYNCIO调试、绑定CPU核心、用Semaphore限并发、复用ClientSession、优先TaskGroup结构化异常处理。

Python 3.11 能显著提升网络自动化中的异步 IO 效率,但必须绕开 uvloop 在双核环境下的隐式性能退化问题——否则 QPS 可能倒退 42%,P99 延迟翻三倍。
asyncio.run() 是最简入口,但别在循环中反复调用
很多脚本写成每次请求都 asyncio.run(main()),这会反复创建/销毁事件循环,开销远超协程本身。CPython 3.11 虽优化了帧创建,但循环重建仍触发完整解释器初始化。
- 只在程序顶层调用一次
asyncio.run(),把所有网络任务组织进一个主协程 - 若需多次执行(如定时轮询),改用
asyncio.get_event_loop().run_until_complete()复用已有循环 - 避免在
for循环里嵌套asyncio.run(),否则每轮都重载 GIL 状态、重建调度器
uvloop 加速有前提:必须禁用细粒度 GIL 干扰
CPython 3.11 默认启用 per-interpreter GIL,与 uvloop 的 libuv 线程池回调不兼容,导致 epoll_wait 频繁阻塞 >50ms。这不是 uvloop 的 bug,而是 Python 层线程状态未同步所致。
- 启动前设置环境变量:
PYTHONASYNCIODEBUG=0(关闭调试模式,它会放大 GIL 冲突) - 显式绑定 CPU 核心并限制线程池:
LIBUV_THREADPOOL_SIZE=2 taskset -c 0 python app.py - 更稳妥的做法是暂弃 uvloop,直接用 CPython 3.11 自带的
asyncio.SelectorEventLoop——实测在万级连接下吞吐稳定,且无跨核调度抖动
并发控制别只靠 asyncio.gather(),要设硬限
asyncio.gather(*tasks) 默认并发全部发起,对目标服务或本地文件描述符数都是风险。Python 3.11 的更快函数调用反而会让失控并发更快打崩下游。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
立即学习“Python免费学习笔记(深入)”;
- 用
asyncio.Semaphore(10)限制同时请求数,防止触发目标限流或本地Too many open files - 对 HTTP 客户端,复用
aiohttp.ClientSession实例,避免重复建连和 DNS 解析 - 批量任务建议分片提交:
gather(*chunk)+await asyncio.sleep(0)让出调度权,缓解事件循环饥饿
异常传播必须用 TaskGroup,别信 asyncio.wait()
Python 3.11 正式支持结构化并发,asyncio.TaskGroup 能保证子任务异常立即中断全体,而 asyncio.wait() 或裸 create_task() 会静默吞掉错误,导致超时后才暴露问题。
- 替换旧写法:
async with asyncio.TaskGroup() as tg:替代tasks = [create_task(...)] - 子任务内抛出异常会立刻终止其他正在运行的协程,并把原始 traceback 透出到
TaskGroup作用域 - 注意:若用
asyncio.create_task()手动管理,必须显式await task或检查task.exception(),否则异常被丢弃
真正卡住效率的往往不是协程语法,而是 GIL 绑定策略、线程池大小、文件描述符限制这些底层联动点。Python 3.11 的性能收益只在参数对齐时兑现,错配时反而比 3.10 更脆。

















