多版本 Python 思考

主要观点:随着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.pybar/baz.py
  • 多版本包放置在.venv/multi-version-packages/下,需自定义导入钩子并注册代理以解决sys.modules中的问题。
  • 解决确定导入版本的问题需利用globals()获取导入模块的包名,对于 C 扩展需通过栈回溯或携带当前活动的 C 扩展模块来确定触发导入的.so/.dylib文件。
  • 目前缺乏将sys.module条目与 PyPI 分发名称映射的 API,安装器可能需将分发名称关联到模块上。
  • 端到端解决方案包括将多版本包安装在site-packages外,在模块上实现__distribution__字段或提供映射 API,修补__import__函数,以及在sys.modules中注册代理条目。
阅读 9
0 条评论