主要观点:随着uv的快速发展,开始重新研究为 Python 实现多版本导入。目标是让求解器能够在 uv 中进行多种解析,以便同时安装和使用两个不兼容版本的库。
关键信息:
- Python 的导入系统将模块置于模块缓存中,通过
sys.modules
暴露。 - 不同版本的库在
sys.modules
中可能会冲突,需将多版本包放置在不同位置,并使用自定义导入钩子导入。 - 需根据调用包的包元数据来确定导入的库版本,目前存在导入钩子不知哪个模块触发导入、Python 模块不知其分发包等挑战。
- 要确定调用的 Python 模块及相关的 PyPI 分发名称,目前的
importlib.metadata.packages_distributions
方法有局限性。
重要细节: foo.py
是 Python“模块”,在sys.modules
中注册为'foo'
,foo/__init__.py
既是模块也是包,有__path__
和__package__
属性。- 分发包可包含多个模块,如
whatever
包包含foo.py
和bar/baz.py
。 - 多版本包放置在
.venv/multi-version-packages/
下,需自定义导入钩子并注册代理以解决sys.modules
中的问题。 - 解决确定导入版本的问题需利用
globals()
获取导入模块的包名,对于 C 扩展需通过栈回溯或携带当前活动的 C 扩展模块来确定触发导入的.so
/.dylib
文件。 - 目前缺乏将
sys.module
条目与 PyPI 分发名称映射的 API,安装器可能需将分发名称关联到模块上。 - 端到端解决方案包括将多版本包安装在
site-packages
外,在模块上实现__distribution__
字段或提供映射 API,修补__import__
函数,以及在sys.modules
中注册代理条目。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。