- 开发工具
- CLI
- 包管理器
- 任务调度
【免费下载链接】pixi
Powerful system-level package manager for Linux, macOS and Windows written in Rust – building on top of the Conda ecosystem.
导读
Pixi 是基于 Conda 生态的跨平台(Linux / macOS / Windows)包管理器,允许你在同一个 Workspace中声明多个相互独立的环境(Environment)。本文以官方教程 docs/tutorials/multi_environment.md 为主体,完整演示如何通过[environments]与[feature]表拆分开发、测试、生产等不同用途的环境,如何用solve-group保证各环境依赖版本一致,以及如何在 CI 矩阵中并行测试多个 Python 版本。读完本文你将掌握:Environment / Feature / Default 三个核心概念、在 manifest 中直接声明环境依赖与任务、用命令行切换与运行指定环境、以及用no-default-feature构建"轻量专用环境"的完整套路。
为什么需要多环境?
在开发一个 Workspace 时,不同角色对工具链的需求往往截然不同:
- 开发者需要尽可能多的工具与库(如 JupyterLab、调试器、格式化工具);
- 测试基础设施只需要被测项目加上测试框架(如 pytest);
- 生产环境则希望依赖越少越好,只保留项目运行所必需的内容。
传统做法是为每种场景单独维护一套环境,手动同步依赖版本,费时且容易漂移。Pixi 的多环境机制把这些问题集中到一个 manifest 文件里解决:一个 Workspace 可以定义任意多个环境,随时用一条命令切换。
核心术语速览
先建立三个贯穿全文的概念(均可在 manifest 参考文档 docs/reference/pixi_manifest.md 中查到更完整定义):
Environment(环境)一个环境是依赖、任务等内容的集合,可以被安装、激活并用于运行任务。你可以在一个 Workspace 中定义多个环境,定义方式是在 manifest 的[environments]表中添加条目。环境的内容既可以直接内联声明(如[environments.<name>.dependencies]),也可以通过feature引入共享内容。从源码结构看,crates/pixi_manifest/src/environment.rs 中的Environment结构体正好对应这三个关键字段:features(组成该环境的 feature 列表)、solve_group(求解分组)、no_default_feature(是否排除默认 feature)。
Feature(特性)Feature 定义环境的"一部分内容",单独存在时没有意义,必须被某个环境引用。它的存在意义是在多个环境之间共享内容:一个 feature 可以包含tasks、dependencies、platforms、channels以及更多内容(参见参考文档中的 The Feature Table)。多个 feature 可以自由组合成一个环境。Feature 通过在 manifest 中添加[feature.<name>.*]表来定义。
Default(默认 feature)如果不写[feature.<name>.dependencies],而是直接写[dependencies],那么这些顶层表会被归入名为default的 feature。default会被自动加入每一个环境(除非该环境显式设置no-default-feature = true退出默认继承)。default是受保护的保留名,不能用于自定义 feature(参见 crates/pixi_manifest/src/environment.rs 附近的解析逻辑与 docs/reference/pixi_manifest.md 中的说明)。
开始动手:初始化一个多环境 Workspace
从全新 Workspace 开始(已有 Pixi Workspace 可跳过此步):
pixi init workspace cd workspace pixi add python此时 Workspace 结构如下:
├── .pixi │ └── envs │ └── default ├── pixi.lock └── pixi.toml注意.pixi/envs/default目录:当没有指定环境时,Pixi 会创建或使用名为default的环境。这是所有环境约定俗成的默认入口,也是后续内容展开的基准。
添加一个环境:把依赖直接内联到环境上
现在给 Workspace 加一个简单的test环境。如果这个环境不与其他环境共享内容,就完全不需要 feature——直接编辑pixi.toml,把依赖写在环境表上即可:
[environments.test.dependencies] pytest = "*"(完整示例文件见 docs/source_files/pixi_tomls/multi-environment-simple.toml 中的test-env-dep片段。)
这张表的行为与普通dependencies表完全一致,唯一区别是该依赖只属于test环境。从 manifest 编辑实现来看,crates/pixi_manifest/src/manifests/document.rs 支持把features、solve-group、内联内容等直接写入环境条目,命令行工具如pixi add --environment test pytest也会把依赖写到环境的 inline 表上(而不是顶层表)。
在指定环境中运行任务
环境定义好后,可以立即在其中运行命令:
pixi run --environment test pytest --version这条命令会创建(首次运行时安装)test环境,并在其中执行pytest --version。执行后.pixi/envs目录会多出test子目录:
├── .pixi │ └── envs │ ├── default │ └── test用pixi list可以查看指定环境的内容:
pixi list --environment test--environment(短参数-e)是贯穿 Pixi 各命令的通用标志:pixi run用它指定运行环境(见 crates/pixi_cli/src/run.rs 中pub environment: Option<String>参数定义),pixi list、pixi add、pixi update、pixi upgrade等命令同样支持(例如 crates/pixi_cli/src/update.rs 和 crates/pixi_cli/src/upgrade.rs)。
把测试任务绑定到环境
如果某些测试命令始终只属于test环境,可以直接把任务也写进该环境:
[environments.test.tasks] test = "pytest"(完整示例见 multi-environment-simple.toml 的test-env-tasks片段。)
这样运行测试时就不必再指定环境了:
pixi run test在本例中,它等价于pixi run --environment test pytest。如果多个环境存在同名任务,Pixi 会弹出对话框让你选择在哪个环境中运行该任务(从 crates/pixi_cli/src/run.rs 附近的实现可见,只有在多个环境可用时才会打印环境选择提示)。
实战一:用多环境测试多个 Python 版本
这是开发 Python 库时最常见的需求:同一个项目针对多个 Python 版本跑测试。该工作流可以推广到任何"用不同依赖组合做多套测试"的场景。
先假设你已完成上一节的步骤,Workspace 里已有test环境。为了让 Python 版本在各个环境中可以自由变化,先把顶层python的版本约束放宽为*:
pixi add "python=*"接下来需要两个共享测试工具、但 Python 版本不同的环境。这正是 feature 的用武之地——把pytest依赖挪进一个testfeature,让每个环境各自声明自己的 Python 版本:
# 测试工具是共享的,因此放在 feature 里 [feature.test.dependencies] pytest = "*" [feature.test.tasks] test = "pytest" # Python 版本是每个环境独有的,因此内联声明 [environments.test-py311] dependencies = { python = "3.11.*" } features = ["test"] [environments.test-py312] dependencies = { python = "3.12.*" } features = ["test"](完整示例见 docs/source_files/pixi_tomls/multi-environment-py-envs.toml 的py-envs片段。)
注意这里features = ["test"]只显式列出了一个 feature,但由于没有设置no-default-feature,defaultfeature(即顶层[dependencies]、[tasks]等)仍会被隐式并入——这正是上面把python放宽到*的原因,让各环境的内联python版本约束来决定最终版本。
现在可以在两个环境中分别跑测试:
pixi run --environment test-py311 test pixi run --environment test-py312 test # 或者直接用任务名,Pixi 会弹出对话框让你选择环境 pixi run test这套流程可以直接平移到 CI,用矩阵并行测试多个环境。下面是 GitHub Actions 的示例配置(更多细节见 GitHub Actions 集成文档):
test: runs-on: ubuntu-latest strategy: matrix: environment: [test-py311, test-py312] steps: - uses: actions/checkout@v4 - uses: prefix-dev/setup-pixi@v0 with: environments: ${{ matrix.environment }} - run: pixi run -e ${{ matrix.environment }} testprefix-dev/setup-pixi的environments参数会预先安装矩阵中指定的环境,随后pixi run -e <env> test直接在该环境内执行任务。
实战二:开发 / 测试 / 生产三环境并存
假设一个干净 Workspace(若你一直跟着上文操作,建议pixi init production_project新开一个):
pixi init production_project cd production_project和之前一样,先创建多个 feature:
pixi add numpy python # default feature pixi add --feature dev jupyterlab pixi add --feature test pytest注意第一条命令不带--feature,因此numpy、python进入顶层表(即 default feature);后两条分别把jupyterlab写进devfeature、pytest写进testfeature。
然后按使用场景添加三个环境:
production:只包含defaultfeature——这是项目运行的最基本内容;test:包含test+default两个 feature——既要测项目,又需要测试工具;default:包含dev+test两个 feature,作为本地开发主力环境,这样日常跑任务无需指定环境。
之所以用 feature 而不是内联声明,是因为testfeature 被test与default两个环境共享;同时default环境本身无法直接声明依赖(顶层表的内容已经归属 default feature,若在[environments.default.dependencies]内联声明则只属于该环境本身,不会进入共享逻辑,参见 docs/reference/pixi_manifest.md)。
再给这三个环境加上solve-group: prod。solve-group 的作用是让同一组环境在求解阶段被当作"同一个环境"来解析,从而保证production环境与default、test环境拿到完全相同的依赖版本——只是各自只安装自己需要的子集。这样能确保项目在所有环境中的运行行为一致。这一点在 crates/pixi_manifest/src/environment.rs 有明确的源码注释:同属一个 solve-group 的所有环境依赖会被一起求解;参考文档也说明其典型用途是"用带测试依赖的环境去测生产环境"(见 docs/reference/pixi_manifest.md 的solve-group字段说明)。
用pixi workspace environment add命令完成配置(该子命令是pixi workspace系列中用于编辑环境表的一部分):
pixi workspace environment add production --solve-group prod pixi workspace environment add test --feature test --solve-group prod # --force 用于覆盖已存在的 default 环境 pixi workspace environment add default --feature dev --feature test --solve-group prod --force运行pixi list -x(-x表示"展开/详细"列出环境依赖,-e指定环境)可以看到三个环境拥有完全相同的依赖版本:
# Default environment Package Version Build Size Kind Source jupyterlab 4.3.4 pyhd8ed1ab_0 6.9 MiB conda jupyterlab numpy 2.2.1 py313ha4a2180_0 6.2 MiB conda numpy pytest 8.3.4 pyhd8ed1ab_1 253.1 KiB conda pytest python 3.13.1 h4f43103_105_cp313 12.3 MiB conda python Environment: test Package Version Build Size Kind Source numpy 2.2.1 py313ha4a2180_0 6.2 MiB conda numpy pytest 8.3.4 pyhd8ed1ab_1 253.1 KiB conda pytest python 3.13.1 h4f43103_105_cp313 12.3 MiB conda python Environment: production Package Version Build Size Kind Source numpy 2.2.1 py313ha4a2180_0 6.2 MiB conda numpy python 3.13.1 h4f43103_105_cp313 12.3 MiB conda python可以看到:default拥有全部依赖(dev 工具 + 测试工具 + 运行依赖),test去掉了jupyterlab,production只保留numpy和python;而numpy、python、pytest的版本号在三个环境中完全一致——这正是 solve-group 的效果。
实战三:no-default-feature构建"纯净"专用环境
当某个环境不需要继承defaultfeature时,用no-default-feature = true显式退出默认继承。这样环境里只包含你显式指定的内容。
一个典型场景是文档生成环境:文档工具(如 mkdocs)只需要在一个环境里用到,没必要混入项目依赖。此时既可以把依赖直接内联到该环境上,又不让 default feature 掺和进来:
[environments.docs] dependencies = { mkdocs = "*" } no-default-feature = true(完整示例见 docs/source_files/pixi_tomls/multi-environment-docs.toml 的docs-env片段。)
运行pixi list -x -e docs可以看到该环境只含mkdocs一个依赖:
Environment: docs Package Version Build Size Kind Source mkdocs 1.6.1 pyhd8ed1ab_1 3.4 MiB conda mkdocs参考文档 docs/reference/pixi_manifest.md 对no-default-feature的默认值说明是false(即默认包含 default feature)。还有一个易被忽视的细节:即使某个环境设置了no-default-feature = true,[workspace.pypi-options]作为 Workspace 基础配置仍会应用于所有环境(见 docs/reference/pixi_manifest.md 附近的说明),也就是说"退出默认"针对的是 feature 内容,而非全局配置。
环境合并的语义:多 feature 组合时的规则
当多个 feature(含 default)组合成一个环境时,参考文档明确了合并规则(详见 docs/reference/pixi_manifest.md):
- activation 与 tasks:取所有 feature 的并集;
- dependencies 与 pypi-dependencies:取所有 feature 的并集;若多个 feature 对同一个包声明了不同要求,两者会被合并约束,需要注意跨 feature 的冲突;
- channels:取所有 feature 的并集,可通过每个 feature 的
channel-priority控制优先级; - platforms:取所有 feature 的交集;feature 未覆盖 platforms 时默认沿用 Workspace 级 platforms,因此通常建议把 Workspace 的
platforms设为所有环境能支持的平台全集; - 内联内容优先于引用的 feature:在顺序敏感的字段(如
tasks、activation)上,环境的内联内容排在 feature 内容之前(crates/pixi_manifest 与 docs/reference/pixi_manifest.md 均有说明)。
此外,内联在环境上的内容是该环境私有的,不能被其他环境引用;这一点对default环境同样成立——写在[environments.default.*]的内容只属于 default 环境,而顶层表(如[dependencies]、[tasks])属于 default feature,会被所有未设置no-default-feature的环境继承(见 docs/reference/pixi_manifest.md 附近的说明)。
小结与延伸阅读
多环境机制把"一套依赖、多种用途"的组织成本降到最低:用feature共享内容、用[environments] 内联声明表达独有内容、用solve-group锁定跨环境版本一致性、用no-default-feature构造纯净专用环境。无论是多版本 Python 测试矩阵,还是开发/测试/生产三环境拆分,都能在一个 manifest 文件内声明清楚,并用pixi run -e <env>、pixi list -e <env>等命令随时切换验证。
- 想要更完整的字段定义与组合语义,参见参考文档的 The Feature and Environments tables 一节;
- 想要更深入的设计动机与进阶用法(如 feature 平台绑定、激活脚本与变量的按环境隔离),参见进阶文档 Workspace 多环境;
- 环境相关数据结构(
Environment、NewEnvironment、EnvironmentName)可直接阅读 crates/pixi_manifest/src/environment.rs; - 配套的完整 manifest 示例文件位于 docs/source_files/pixi_tomls/multi-environment-simple.toml、docs/source_files/pixi_tomls/multi-environment-py-envs.toml 与 docs/source_files/pixi_tomls/multi-environment-docs.toml,可直接复制到自己的 Workspace 验证。
- 开发工具
- CLI
- 包管理器
- 任务调度
【免费下载链接】pixi
Powerful system-level package manager for Linux, macOS and Windows written in Rust – building on top of the Conda ecosystem.
相关推荐
Pixi 多环境管理:pixi workspace environment add 命令详解与实战
Pixi 多环境管理:pixi workspace environment add 命令详解与实战 pixi workspace environment add
开发工具CLI包管理器任务调度Chainer-fast-neuralstyle常见问题解决:从环境配置到模型训练
Chainer fast neuralstyle常见问题解决:从环境配置到模型训练 Chainer fast neuralstyle是一个基于Chainer框架
用 Python 与 Flet 从零构建 Klondike 纸牌游戏:完整实战教程
用 Python 与 Flet 从零构建 Klondike 纸牌游戏:完整实战教程 本教程将以 Flet 开源仓库中的 Solitaire 教程为蓝本,带你从环
前端跨平台桌面应用移动开发
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考