Rye 依赖管理实战指南:从 `pyproject.toml` 到 `rye add` 的完整解析
2026/9/22 11:11:04 网站建设 项目流程

Rye 依赖管理实战指南:从pyproject.tomlrye add的完整解析

【免费下载链接】ryea Hassle-Free Python Experience项目地址: https://gitcode.com/gh_mirrors/ry/rye

导读:本文围绕 Rye 官方指南 deps.md 展开,系统讲解如何在 Rye 管理的 Python 项目中声明与维护依赖:从最基础的rye add普通依赖、PEP 508 版本约束、extras 特性依赖,到开发依赖、Git/本地路径依赖与 workspace 协作。同时结合本仓库的 Rust 源码(rye/src/cli/add.rs、rye/src/pyproject.rs)与测试用例(rye/tests/test_add.rs),剖析依赖写入pyproject.toml的底层机制与参数语义。读完本文,你将掌握 Rye 中依赖声明、添加、移除与同步的完整工作流,并能根据项目场景选择最合适的依赖类型。

依赖声明的核心:pyproject.toml+rye add

在 Rye 中,所有依赖最终都声明在项目的 pyproject.toml 中。虽然你可以手工编辑该文件,但 Rye 提供了更友好的rye add命令来简化这一过程——它接受 PEP 508 需求字符串作为输入,同时提供一系列辅助参数(如--git--path),让"声明依赖"这件事不再需要记忆冗长的语法。

Rye 对project.dependencies这一键不做任何私有化改造——它完全符合标准pyproject.toml的语义,只是 Rye 具备通过rye add/rye remove自动修改这些条目的能力。也就是说:rye add写进去的内容,和手写标准 PEP 508 字符串完全等价

从源码看,rye add的核心执行流程(rye/src/cli/add.rs)分为三步:

  1. 解析传入的 PEP 508 需求字符串,并应用--git--path--features等参数改写为最终需求(ReqExtras::apply_to_requirement);
  2. 借助内置的 uv 解析器解析出可用的最新版本,并按照默认或指定的 pin 操作符生成版本约束;
  3. 调用PyProject::add_dependency把需求写入对应的 TOML 键(rye/src/pyproject.rs),最后按需触发自动同步(autosync)。

依赖在 TOML 中的归属

根据DependencyKind枚举(rye/src/pyproject.rs),Rye 支持四类依赖写入位置:

依赖类型写入位置触发参数
普通依赖(regular)project.dependencies默认
开发依赖(dev)tool.rye.dev-dependencies--dev
排除依赖(excluded)tool.rye.excluded-dependencies--excluded
可选分组依赖(optional)project.optional-dependencies.<分组名>--optional <名称>

源码中add_dependency函数(rye/src/pyproject.rs)正是按这个映射将需求写入不同键位,且会自动创建缺失的数组或表。这与 pyproject.md 中project.dependenciestool.rye.dev-dependencies等键的说明一一对应。

添加基础依赖

添加普通依赖最简单的方式,就是直接用包名调用rye add

rye add Flask

该命令会先初始化/复用项目虚拟环境,随后解析出当前 Python 版本下兼容的最新版本,并以>=操作符写入project.dependencies,最后自动生成requirements.lockrequirements-dev.lock并安装依赖。测试 rye/tests/test_add.rs 中记录的真实输出为:

$ rye add flask colorama Added flask>=3.0.0 as regular dependency Added colorama>=0.4.6 as regular dependency Reusing already existing virtualenv Generating production lockfile: requirements.lock Generating dev lockfile: requirements-dev.lock Installing dependencies Done!

对应的pyproject.toml片段:

[project] dependencies = [ "flask>=3.0.0", "colorama>=0.4.6", ]

指定版本:使用 PEP 508 需求字符串

如果想控制版本,直接传入 PEP 508 需求字符串即可:

rye add "Flask>=2.0" rye add "werkzeug==3.0.0"

注意测试 test_add_explicit_version_or_url 显示:当你显式给出完整版本(如==3.0.0)时,Rye 会保留原样写入,不再解析追加操作符;而只给包名时才会自动补上解析得到的最新版本与默认操作符。

默认版本操作符的定制

Rye 默认使用>=作为自动 pin 操作符,但这一行为可通过全局配置dependency-operator调整(rye/src/config.rs):

# config.toml [default] dependency-operator = "~=" # 可选:">="(默认)、"=="、"~="

此外,rye add还提供--pin参数,在单次命令中覆盖该默认值,可选值为equal==)、tilde-equal~=)、greater-than-equal>=),并支持==~=>=exactcompatible等别名(见 rye/src/cli/add.rs):

rye add Flask --pin=tilde-equal # 写入 flask~=<解析版本>

从源码看,解析出的版本约束还会做两个细节处理(rye/src/cli/add.rs):对带本地版本号(local version)的版本强制使用==;当~=目标版本只有一位 release 时降级为>=

extras 特性依赖(feature / extra)

Python 包通常提供可选的 extras(特性),Rye 支持两种等价写法:

rye add "Flask[dotenv]" # 直接在 PEP 508 字符串中声明 rye add Flask --features=dotenv # 使用 --features 参数

--features参数在源码中按逗号切分并去重后合并进需求的extras字段(rye/src/cli/add.rs),因此也支持一次传入多个特性:

rye add Flask --features=dotenv,async

两种写法最终写入project.dependencies的效果一致,例如"flask[dotenv]>=3.0.0"。测试 test_add_flask_dotenv 证实:添加flask[dotenv]后,解析结果中会额外安装python-dotenv

关于预发布版本(pre-releases)的重要提示

默认情况下,rye add不会考虑预发布版本。如果你添加的依赖在版本号中带有.devrc等预发布标识,将无法解析到匹配项。此时需要显式传入--pre

rye add "Flask==2.0.0rc2" --pre

从源码看,--pre会一路传递给 uv 解析器(uv.resolve(..., pre, ...),见 rye/src/cli/add.rs),控制其是否允许预发布匹配。

开发依赖(Development Dependencies)

只用于开发阶段(如格式化、静态检查工具)的依赖,用--dev添加:

rye add --dev black

开发依赖不会被写入标准的project.dependencies,而是存放在 Rye 私有的tool.rye.dev-dependencies键中(pyproject.md):

[tool.rye] dev-dependencies = ["black~=23.3.0"]

对应的源码映射见 rye/src/pyproject.rs:--devadd_dependency会往tool.rye表的dev-dependencies数组追加条目(不存在则自动创建)。测试 test_add_dev 展示了pyproject.tomltool.rye表的最终形态。

rye run运行开发工具

开发依赖默认随rye sync安装进虚拟环境,但不需要手动激活虚拟环境即可运行其中的工具——直接用rye run

rye run black

rye run会优先在虚拟环境中查找并执行对应命令,这一机制同样适用于 tool.rye.scripts 中注册的自定义脚本。若希望sync时不安装开发依赖,可传--no-dev(详见 sync.md)。

排除依赖(Excluded Dependencies)

tool.rye.excluded-dependencies是一个特殊键:其中的依赖永远不会被安装,即使它们作为间接依赖(子依赖)被拉取进来。使用rye add --excluded自动添加:

rye add --excluded cffi
[tool.rye] excluded-dependencies = ["cffi"]

在源码中,DependencyKind::ExcludedDev一样写入tool.rye表(rye/src/pyproject.rs),且--excluded--dev--optional互斥(rye/src/cli/add.rs)。这一功能在项目与某个传递依赖存在兼容性冲突时非常实用。

可选依赖组(Optional Dependency Groups)

通过--optional可以将依赖加入标准project.optional-dependencies下的命名分组:

rye add --optional=web flask

写入后的 TOML:

[project.optional-dependencies] web = ["flask>=3.0.0"]

该分组在rye lock/rye sync时可通过--features=web启用(参见 sync.md 的--features说明)。源码中,--optional--dev--excluded互斥,且会创建project.optional-dependencies表及对应分组(rye/src/pyproject.rs)。

Git / 本地路径依赖

当依赖来自 Git 仓库或本地目录时,可以传--git--url--path参数,无需在需求字符串里手工拼接:

rye add Flask --git=https://github.com/pallets/flask rye add My-Utility --path ./my-utility rye add pip --url=https://example.com/pip-1.3.1.zip

注意:使用这些参数时必须同时提供包名--path/--git/--url与一次传多个需求不兼容,源码中对此有显式校验,见 rye/src/cli/add.rs)。且这些参数会与需求字符串中已有的版本约束冲突——如果需求已经带有版本标记,会直接报错"requirement already has a version marker"(rye/src/cli/add.rs)。

Git 依赖的 tag / rev / branch

Git 依赖支持额外的定位参数:

rye add Flask --git=https://github.com/pallets/flask --tag=3.0.0 rye add Flask --git=https://github.com/pallets/flask --rev=abc1234 rye add Flask --git=https://github.com/pallets/flask --branch=main

源码实现中(rye/src/cli/add.rs),--rev--tag--branch三选一(互斥)拼接为git+<url>@<ref>形式的 URL;--tag/--rev/--branch均要求同时存在--git。测试输出示例:

$ rye add flask --git https://github.com/pallets/flask Added flask @ git+https://github.com/pallets/flask as regular dependency

本地路径依赖与--absolute

--path依赖最终会写成file://URL。默认情况下 Rye 会尝试生成基于${PROJECT_ROOT}的相对路径,以便项目迁移;但当构建后端为 hatchling(其{root:uri}写法不被 uv 支持),或显式传入--absolute时,会强制生成绝对路径(rye/src/cli/add.rs)。--absolute需要同时传入--path

rye add My-Utility --path ./my-utility --absolute

本地依赖强烈建议配合 workspace

当项目依赖本地包时,官方指南强烈建议将其配置为 workspace 成员。workspace 让子目录中的 Python 项目共享同一个虚拟环境与锁文件,从而保证本地依赖与主项目在解析、安装时的一致性。配置方式(详见 workspaces.md):

[tool.rye.workspace] members = ["mylib-*"]

移除依赖

与添加对称的是rye remove(命令参考见 remove.md):

rye remove flask rye remove black --dev # 移除开发依赖 rye remove flask --optional=web # 移除可选分组依赖

它会从pyproject.toml对应的依赖列表中删除条目(rye/src/pyproject.rs 中的remove_dependencyadd_dependency使用相同的键位映射)。与add一样,是否立即同步安装状态取决于 auto-sync 设置。

自动同步(auto-sync)与--sync/--no-sync

rye add/rye remove之后依赖是否立刻被安装,由全局配置behavior.autosync(默认开启)决定(rye/src/config.rs):

  • 若 auto-sync 关闭,添加依赖后不会自动安装,需要手动rye sync,或本次命令显式传--sync
  • 若 auto-sync 开启但本次不想同步,可传--no-sync--sync--no-sync互斥,见 rye/src/cli/add.rs)。
rye add flask --sync # 即使 auto-sync 关闭也立即同步 rye add flask --no-sync # 即使 auto-sync 开启也跳过同步

execute主流程看(rye/src/cli/add.rs),同步条件为(autosync && !no_sync) || sync,满足时调用autosync完成锁文件生成与虚拟环境安装。所谓同步,本质是更新两份锁文件(requirements.lockrequirements-dev.lock)并用它们重建虚拟环境,锁定的完整参数说明见 sync.md。

从源码理解rye add的完整调用链

汇总rye add的底层链路,便于读者深入阅读仓库:

  1. 参数解析ArgsReqExtras结构体定义全部命令行参数及互斥/依赖关系(rye/src/cli/add.rs);
  2. 需求构造Requirement::from_str解析 PEP 508 字符串,ReqExtras::apply_to_requirement应用--git/--url/--path/--features(rye/src/cli/add.rs);
  3. 版本解析resolve_requirements_with_uv通过内置 uv 解析器找到最新兼容版本,并按默认操作符生成版本约束(rye/src/cli/add.rs);
  4. 写入 TOMLPyProject::add_dependencyDependencyKind写入对应键位(rye/src/pyproject.rs);
  5. 自动同步:按 auto-sync 配置调用autosync完成 lock + install。

完整的行为快照(含真实输出、最终 TOML 内容)可在测试文件 rye/tests/test_add.rs 中逐一验证,覆盖普通依赖、extras、dev 依赖、显式版本、URL 依赖、自定义 sources 等场景,是学习rye add语义的最佳参考。

小结

  • 普通依赖rye add <包名>,写入project.dependencies,支持 PEP 508 版本约束与--pin定制操作符;
  • 特性依赖:PEP 508 的[extra]写法与--features等价;
  • 开发依赖--dev写入tool.rye.dev-dependencies,用rye run免激活运行;
  • 排除/可选依赖--excluded--optional <组名>对应tool.rye.excluded-dependenciesproject.optional-dependencies
  • Git/本地依赖--git(配--tag/--rev/--branch)、--url--path(配--absolute),本地依赖建议纳入 workspace;
  • 同步控制:受autosync全局配置影响,可用--sync/--no-sync覆盖单次行为。

完整命令参数清单可参考 add.md,配置文件各键的权威解释见 pyproject.md。

【免费下载链接】ryea Hassle-Free Python Experience项目地址: https://gitcode.com/gh_mirrors/ry/rye

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询