GitHub - MagicStack/uvloop: Ultra fast asyncio event loop. · GitHub
GitHub - Vizonex/Winloop: An Alternative library for uvloop compatability with windows · GitHub
📝 巧用"替身攻击"解决子进程 ModuleNotFoundError: No module named 'uvloop'
场景背景
在 Windows 上开发异步应用时,我们通常会编译并安装 winloop(具体编译过程见这篇前置教程),并在主程序入口通过 winloop.install() 成功替换了原生的 asyncio 事件循环。
在 Windows 11 上从源码编译安装 Winloop (uvloop 高性能事件循环) 保姆级实战指南-CSDN博客

然而,当你运行像 SGLang 这样的多进程框架时,主进程虽然跑通了,但框架在后台启动的全新子进程却直接崩溃,抛出报错:
ModuleNotFoundError: No module named 'uvloop'。

原因分析
子进程是一个相对纯净的独立 Python 环境,它并不知道你在主进程里做过 winloop 的替换。而许多底层框架源码中硬编码 了 import uvloop。当子进程执行到这一行时,因为 Windows 上根本装不上原版 uvloop,自然就崩溃了。
解决方案:本地模块伪装(Module Aliasing)
既然框架非要 uvloop,那我们就利用 Python 的模块导入优先级(当前目录优先),给它造一个"假"的。完全不需要修改框架源码。
-
在你的项目根目录下(即运行脚本的当前目录),新建一个名为
uvloop的文件夹。 -
在该文件夹中新建一个
__init__.py文件。 -
在文件中写入以下三行代码并保存:
Python
import sys
import winloop
# 劫持当前模块,将其替换为 winloop
sys.modules[__name__] = winloop

原理解析
当框架的子进程启动并尝试 import uvloop 时,Python 会优先扫描当前目录。它会进入我们创建的 uvloop 文件夹并执行 __init__.py。此时,我们的代码通过修改 sys.modules,顺水推舟地把 winloop 伪装成了 uvloop 递给了框架。由于两者 API 完全一致,框架会毫无察觉地使用 winloop 继续飞奔。