管理 Python 的环境和依赖一直是个让人头疼的问题,这一点从多年来层出不穷的 Python 包管理工具可见一斑:poetry,conda, micromamba , hatch , pdm, uv...... 不胜枚举。这些工具分散在 Conda 和 PyPI 两大生态中,很多开发者都遇到过:有些包只在 Conda 找得到,有些只能在 PyPI 安装,两头切换非常麻烦。

添加图片注释,不超过 140 字(可选)
Pixi 作为一款支持多语言的包管理器,希望把这两个生态无缝衔接起来:无论是 Conda 包(通过 rattler 库),还是 PyPI 包(通过与 uv 的集成),都可以在同一个项目里一站式使用。
我们的目标是:打破 Conda 和 PyPI 的壁垒,让它们可以同时使用、互相补充。
本文是对官方技术博客 Using Projects with Pixi 的翻译,在原文基础上,译者也补充了一些关系图辅助大家理解Conda和PyPI的映射。
作者:Tim De Jager
译者:Magenta Qin
这和我有什么关系?
如果你是 Python 开发者,但愿意跳出 PyPI 的"舒适圈",去了解一下 Conda 生态,你会发现其实有不少实用的优势:
- 在隔离环境里管理系统级依赖 ------ 比如 SDL、OpenSSL 等,直接用 Conda 配好,省去自己折腾。
- 方便管理非 Python 依赖 ------ 如果你的项目需要 Node、npm、CMake、编译器等工具,用 Conda 一起打包,环境更干净。
- 用 system-requirements(虚拟包)让硬件和环境需求更清晰可控 ------ 比如项目需要 CUDA,加到锁文件里,Pixi会在安装时自动匹配正确的版本。
- 用 pixi add pytorch 时,Pixi 会根据系统自动选 CPU 或 GPU(以及合适的 CUDA 版本); 相比手动执行pip(pip3 install torch --index-url download.pytorch.org/whl/cu118),显然前者更省心。
更重要的是,就算有了这些新特性,你还可以继续延用熟悉的 PyPI 项目结构来管理依赖,同时按需接入 Conda 生态,二者不冲突。

添加图片注释,不超过 140 字(可选)
Pixi 能带来什么?
除了最新的功能更新,使用 Pixi 管理 Python 项目时,你还会自动获得:
- Python 解释器的安装与管理:按项目独立管理,支持所有主流平台。
- 跨平台依赖锁定:为每个主要平台分别锁定依赖,保证可复现性。
- 任务系统(带缓存):在项目里可以高效执行自定义任务,自动缓存避免重复工作。
- 多环境支持: 为同一个项目创建多个环境,灵活切换不同依赖组合(例如不同 Python 版本,或 CUDA / 非 CUDA 环境),并支持各自独立的任务配置。
有什么新变化?
在之前的版本里,Pixi 还有一些尚未支持的功能,可能会让用户在切换到 Pixi 时遇到一些不必要的阻碍。
在最新版本中,我们增加了以下新特性:
- 支持同时使用 pyproject.toml 和 pixi.toml作为 manifest 文件, 更贴合 Python 社区的主流习惯。
- Pixi 支持从 PyPI 安装源依赖,包括可编辑安装(editable installs)。
- 支持更完善的 PyPI-Conda 映射功能,如果某个包已在 Conda 环境中可用,就会自动跳过重复安装。
下面是这些新功能的详细介绍:
Pyproject.toml 支持
在最初设计 Pixi 时,我们引入了 pixi.toml 作为 manifest 文件。
之所以没有直接用 pyproject.toml ,是因为 Pixi 不仅仅支持 Python,还支持多种编程语言。
然而对 Python 开发者来说 ------ 甚至是 Conda 用户 ------ 大家普遍习惯使用 pyproject.toml。
从 Pixi 0.18.0 开始,我们正式推出了对 pyproject.toml 的支持!
对于现有项目,不需要做任何改动,因为 pixi.toml 会优先生效。
所有 Pixi 的独有功能都放在 [tool.pixi.*] 里(pyproject.toml 用户应该对此很熟悉)。
PyPI 源依赖
我们现在支持 直接 URL 依赖(direct url dependencies),即允许直接指定 git 仓库、wheel 文件或 tar.gz 包作为依赖来源。
例如,使用 pixi.toml:
ini
requests = { git = "<https://github.com/psf/requests.git>", rev = "0106aced5faa299e6ede89d123..." }
或者使用 pyproject.toml:
ini
[project]
dependencies = ["flask @ git+ssh://git@github.com/pallets/flask@b90a4f1f4a370e92054b9cc9db0..."]
使用 pyproject.toml 进行可编辑安装(editable install):
ini
[tool.pixi.pypi-dependencies] # 本地路径,会以可编辑模式安装你的项目
test_project = { path = ".", editable = true }
如果使用 pixi.toml,则需要去掉 tool.pixi 前缀。
PyPI ➡️ Conda 映射
Because a lot of python conda packages are repackaged python projects. They can be used interchangeably as dependencies.
你通过 Conda 安装的很多包(例如 conda install pandas),其实最初是从 PyPI(Python 包索引)发布的。这些原生的 PyPI 包,经过再处理,被打包成 Conda 格式(如 .conda 或 .tar.bz2),从而能在 Conda 环境中顺利安装和使用。(译者解释)
换句话说,Conda 与 PyPI 之间本质上是有桥梁的,只是这个桥梁并非自动构建 ------ 需要社区开发者主动维护和转换包格式。 这也是我们构建 Pixi 的初衷之一:
更顺滑地连接 PyPI 和 Conda 两大生态系统,让用户不必再因为"某个包只在 PyPI/Conda 上有"而手动切换工具链。
有时候会出现这种情况:你安装的某个 Conda 包是 PyPI 包的依赖项。例如,你已经通过 Conda 安装了 click 包,同时又需要使用 flask 这个 PyPI 包,而 flask 依赖 click。
遇到这种场景,可以这样写 pixi.toml,简单清晰:
ini
[project]
name = "test"
version = "0.1.0"
description = "测试 PyPI 和 Conda"
authors = ["Tim de Jager <tim@prefix.dev>"]
channels = ["conda-forge"]
platforms = ["osx-arm64"]
[tasks]
[dependencies]
# We depend on click as conda dependency
click = "*"
[pypi-dependencies]
# flask also depends on click, as a pypi dependency
flask = "*"
在 Pixi 中,我们会把 Conda 里的 click 包作为 flask 的依赖来使用,也就是用 Conda 的 click 来覆盖掉来自 PyPI 的 click。
另外,译者在这里也补充整理了常见的几种case,方便大家理解映射机制。一句话概括: Pixi会默认优先选择Conda 版本。
case 1,同名包,Conda 包覆盖 PyPI 包。

添加图片注释,不超过 140 字(可选)
case 2: 同名包版本冲突。这里假设存在两个同名包的包版本冲突:
- pypi-seaborn@1.0.0 vs pypi-seaborn@2.0.0
- conda-pandas@1.0.0vsconda-pandas@2.0.0
Pixi的策略是:只保留一个版本。根据用户选择的 Conda包版本,反向去选择要安装的 PyPI 包版本。如果用户选择了 conda-pandas@1.0.0,则安装的是依赖conda-pandas@1.0.0的pypi-seaborn@1.0.0。pypi-seaborn@2.0.0 和 conda-pandas@2.0.0 则被排除在外。

添加图片注释,不超过 140 字(可选)
以前我们用过 grayskull 映射工具来做这件事,👉 Grayskull。不过,grayskull 的映射 有一个限制:需要你手动维护---为了匹配不同包的命名,你必须手动把要用的包添加到配置文件里。
所以为什么不进一步把整个流程完全自动化呢?
我们分析了 超过 1,700,500 个 conda-forge 的包,并且每小时都会自动更新,追踪新包。我们会根据 conda 包的路径信息,自动提取出对应的 Python 包名和版本。通过这一策略,我们额外识别出了 3,807 个新包例如(redisgraph-py , scikit-geometry, cloudpathlib-s3等)。Conda 包与 PyPI 包的映射准确率提升了 **24.66%。**这个策略带来了两个显著优势:
- 适用于所有 Conda Channel,无需手动维护映射列表。这意味着我们不再依赖静态配置,而是可以动态地处理不同来源的包。
- 有效避免同名包的混淆。很多时候,Conda 和 PyPI 上的包虽然名字一样,实际却完全不同。比如: 一个典型的例子是pandoc------ Conda 上的 pandoc 实际指的是 Haskell 库,而在 PyPI 上,pandoc 是另一个完全不同的 Python 包。 而如果不做映射处理,容易被误认为是同一个包,从而引发一系列问题。
在 Pixi,我们非常重视开发者体验,也尽量减少那些"意外惊喜"(毕竟生活里,惊喜最好只是来自一杯好咖啡 ☕️😂)
我们包映射系统非常智能,这类问题都能被正确识别和处理 ------ 两个pandoc都可以被准确区分、正确安装。
👉 点击这里看看我们是怎么做的(parselmouth 项目)
我们还整理了一些与 Grayskull 映射的对比数据 👇

添加图片注释,不超过 140 字(可选)
示例演示
下面的示例会展示前文提到的所有功能点。以下面的文件结构为例:
arduino
example_project
├── pixi.lock
├── pyproject.toml
└── test_project
├── __init__.py
└── module.py
我们可以创建一个 pyproject.toml:
ini
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "test_project"
version = "0.1.0"
requires-python = ">=3.9"
dependencies = ["rich"]
# We need to know the platforms for the locking per platform
# as well as the conda channels, this is where we get the python
# executable from
[tool.pixi.project]
name = "test_project"
channels = ["conda-forge"]
platforms = ["linux-64"]
[tool.pixi.pypi-dependencies]
# A local path, which installs your project in editable mode.
test_project = { path = ".", editable = true }
[tool.pixi.tasks]
# A task to run the python module.
start = "python -c 'from test_project import module; module.hello()'"
[tool.pixi.dependencies]
rich = ">=13.7.1,<13.8"
使用下面这个模块:
python
from rich import print
def hello():
print('[italic green]Hello World![/italic green] I am a [bold cyan]Pixi[/bold cyan] install!')
要运行这个示例,只需执行:
arduino
pixi run start
这条命令会自动解析、安装 Conda 和 PyPI 的依赖,并执行 start 任务。
使用pyproject.toml 时,Pixi 会读取 requires-python 并据此匹配 Python 解释器的版本。
ini
[project]
# 将会从 conda-forge 安装 >= 3.9 的版本
requires-python = ">=3.9"
pyproject.toml 中的依赖会被 Pixi 当作 PyPI 依赖来解析:
ini
[project]
dependencies = ["rich"]
[tool.pixi.dependencies]
rich = ">=13.7.1,<13.8"
如果你同时在 Conda 和 PyPI 都指定了同一个依赖,Pixi 会默认优先选择 Conda 的依赖。
结语
我们希望通过这个新版本,进一步缩小 PyPI 和 Conda 生态之间的差距。
无论你是不是 Python 开发者,是否使用过 Conda,都值得试试把 Pixi 加入你的工具箱!
如果你对打包(packaging)有任何问题,欢迎随时通过社交平台找到我们,我们非常乐意与你交流、一起解决问题!
你可以通过以下方式联系我们:
- 在 X(原 Twitter) 上私信我们
- 加入我们的 Discord 社群
- 发邮件给我们
- 关注并参与我们的 GitHub 项目
最后,特别感谢我们的开源贡献者 Olivier Lacroix,他完成了大部分 pyproject.toml 的工作 ------ 我们非常感谢他的卓越贡献!