首页
/ uv 0.4.x 版本演进解析:从非打包项目到命名索引与 PEP 735 依赖组

uv 0.4.x 版本演进解析:从非打包项目到命名索引与 PEP 735 依赖组

2026-09-05 16:33:41作者:霍妲思

本文基于 uv 仓库中的 0.4.x 变更日志 系统梳理 0.4.0 至 0.4.30 共 31 个版本的演进脉络。读完本文,你将掌握 uv 0.4 周期的三大主线变化——非打包(virtual)项目的一等支持、[[tool.uv.index]] 命名索引体系、PEP 735 依赖组——以及 uv builduv publish 两个新命令的引入背景,并能结合仓库源码(如 is_package 判定逻辑与 DependencyGroups 解析器)理解每项特性的实际行为,为升级和排障提供版本能力参照。

0.4 周期的整体定位

0.4.x 是 uv 项目从"通用 Python 包管理器"走向"完整项目生命周期管理"的关键阶段。变更日志开篇(changelogs/0.4.x.md)即点明 0.4.0 的核心目标:为"并非以 Python 包为目标的项目"(Web 应用、数据科学项目等)提供一等支持。随后 31 个补丁版本沿三条主线推进:

  1. 项目模型重塑(0.4.0、0.4.5):引入 virtual 项目、uv build
  2. 索引体系重构(0.4.23、0.4.24、0.4.25):[[tool.uv.index]] 命名索引与 tool.uv.sources 索引绑定;
  3. 依赖声明标准化(0.4.27、0.4.30):PEP 735 dependency-groups.env 文件与 --all-packages

此外还有若干横向能力:uv publish 与 Trusted Publishing(0.4.16)、托管 Python 3.13 与 free-threaded 构建(0.4.9 / 0.4.21 / 0.4.28)、以及一批环境变量(UV_PROJECT_ENVIRONMENTUV_FIND_LINKSUV_NO_SYNCUV_FROZEN/UV_LOCKED)。

各版本核心亮点速览

版本 核心变化
0.4.0 非打包项目一等支持;uv init 默认不建 src/[build-system]--app/--lib 选项
0.4.1 uv export --format requirements-txt;版本规约按序规范化;Windows 注册表发现 Python
0.4.2 uv run 支持 .pyc 文件;uv cache clean 清理悬挂归档
0.4.3 uv sync --frozen --package 无需复制成员 pyproject.toml--verbose 显示构建后端输出
0.4.4 UV_PROJECT_ENVIRONMENT 自定义环境路径;uv export --no-hashesuv init 固定 .python-version
0.4.5 实现 uv build(含 --package--wheel);锁文件剪除不可达包与 wheel
0.4.6 uv build 支持 --build-constraint--require-hashes/--verify-hashesuv tool upgrade 支持多包
0.4.7 uv export 增加 --no-emit-project--output-fileuv cache prune 清理未用 sdist
0.4.8 动态缓存键(tool.uv.cache-keys);uv init 代码引入类型标注;.tgz.tar.gz 同等对待
0.4.9 托管 Python 3.13;uv self update 支持目标版本;uv run --no-sync
0.4.10 uv run 支持 Python 包(__main__.py)与 zip 应用;tool.uv.cache-keys 支持 glob
0.4.11 uv sync/uv export 支持 --no-editable--only-devuvx 生成 shell 补全
0.4.12 支持用户提供预定义解析元数据;Python 解释器不匹配时使工具环境失效
0.4.13 SOCKS 代理支持;最低 Rust 版本提升至 1.81
0.4.14 破坏性变更:uvx shell 补全移至 uvx --generate-shell-completion;本地命名冲突解析提示
0.4.15 回退"无效平台比无效 Python 更兼容"的判定
0.4.16 实现 uv publish 与 Trusted Publishing;--project 参数;free-threaded 解释器选择
0.4.17 uv build --all 构建整个 workspace;uv init --scriptuv init 初始化 Git 仓库
0.4.18 tool.uv.sources 允许每个包多条 source 条目;uv run -m fooUV_NO_SYNC 环境变量
0.4.19 uv run --scriptUV_FIND_LINKS 环境变量;requires-python 上界参与 wheel 过滤
0.4.20 CPython 3.13.0 正式版纳入托管下载并成为 uv python install 默认版本
0.4.21 free-threaded Python 托管安装;HTTP/2;远程(https://)脚本运行;UV_INSECURE_HOST 通配符
0.4.22 构建依赖中尊重 [tool.uv.sources]uv publish 交互式输入
0.4.23 命名索引体系:[[tool.uv.index]] + tool.uv.sources 索引绑定 + explicit 索引
0.4.24 修复索引凭证泄露至锁文件;UV_INDEX_ 认证变量按文档生效
0.4.25 UV_FROZEN/UV_LOCKEDuv pip show --files;缓存版本化支持向后兼容
0.4.26 系统级 uv.toml 配置支持;direct URL 要求可携带静态元数据
0.4.27 PEP 735 dependency-groups--group/--only-group/--no-groupuv lock --dry-run;强制锁文件 schema 版本
0.4.28 +freethreaded 构建请求;禁用进度输出的环境变量
0.4.29 riscv64 平台标签;uv tree 循环依赖处理;带版本号的 Python 可执行文件(Preview)
0.4.30 uv run 支持 .env 与自定义 env 文件;--all-packagesuv publish --check-url

0.4.0:非打包(virtual)项目的一等支持

这是 0.4 周期最重要的一次语义变更,属于破坏性变更。变更日志说明了动机:此前 uv 要求所有项目都能构建成可分发的 Python 包并装入虚拟环境,uv init 创建的项目总是包含 [build-system] 定义,未定义 [build-system] 的存量项目则默认回退到 legacy setuptools 构建后端。但多数用户开发的是 Web 框架应用或脚本集合,而非需要发布到 PyPI 的库——强制 [build-system] 在这些场景下令人困惑且易错。

0.4.0 的新行为总结为四点(引自变更日志原文):

  1. 不再打包/安装未定义 [build-system] 的项目。项目本身不会进入虚拟环境,但其依赖仍会被解析和安装;
  2. 旧行为可通过 pyproject.toml[tool.uv] 段设置 package = true 恢复;
  3. uv init 默认不再创建 src/ 目录、不再定义 [build-system];旧行为可通过 uv init --libuv init --app --package 恢复;
  4. 允许(并推荐)虚拟 workspace 根包含 [project] 定义(此前要求省略),并允许对定义了 [build-system] 的项目通过 package = false 显式禁用打包。

源码印证:is_package 判定逻辑

从源码结构看,该决策的核心入口是 crates/uv-workspace/src/pyproject.rs 中的 is_package 方法,其判定顺序与文档描述完全一致:

/// Returns `true` if the project should be considered a Python package, as opposed to a
/// non-package ("virtual") project.
pub fn is_package(&self, require_build_system: bool) -> bool {
    // If `tool.uv.package` is set, defer to that explicit setting.
    if let Some(is_package) = self.tool_uv_package() {
        return is_package;
    }
    // Otherwise, a project is assumed to be a package if `build-system` is present.
    self.build_system.is_some() || !require_build_system
}

即:tool.uv.package 显式设置时优先采用;否则以是否存在 [build-system] 表推断。这也解释了为什么变更日志中"未定义 [build-system] 的项目默认使用 setuptools 后端"的旧行为在 0.4.0 后被改变——默认路径从"兜底打包"变成了"直接视为 virtual 项目"。

0.4.0 同期其他增强

  • 锁文件对非打包依赖使用 virtual source 标签(PR #6728),便于在 uv.lock 中识别 virtual 项目来源;
  • uv tool install 支持 {package}@{version} 语法(PR #6762);
  • 省略 --hashes 时从 URL fragment 读取哈希(PR #6731);
  • 发布不带 patch 版本的额外 Docker 标签。

值得留意的 bug 修复包括:--frozen 下不再要求 workspace 成员同步(PR #6737)、workspace 失效锁文件时比较 virtual 成员(PR #6754)、trusted host 的补全反序列化实现(PR #6716)、以及对 PEP 723 脚本中未闭合 script 标签报错(PR #6704)。

uv build:0.4.5 引入的本地构建命令

0.4.5 实现了 uv build,并在此后四个版本内快速完善,形成完整的本地构建能力:

  • 0.4.5uv build 落地(PR #6895);--package 用于指定 workspace 中要构建的包(PR #6990);默认显示构建输出(PR #6912);支持从 sdist 构建 wheel(--wheel,PR #6898);
  • 0.4.6--build-constraint 约束构建依赖(PR #7085);--require-hashes--verify-hashes 校验构建环境(PR #7094);
  • 0.4.14uv build 输出目录加入 .gitignore(0.4.18,PR #7835);workspace 场景改用顶层输出目录(0.4.18,PR #7813);
  • 0.4.17uv build --all 一次性构建 workspace 全部包(PR #7724);--quiet 生效(PR #7674)。

配套的解析器健壮性改进也在此期间落地:0.4.5 开始锁文件会剪除不可达的包(PR #6959)与 wheel(PR #6961),0.4.7 在 uv cache prune 中清理未使用的 sdist(PR #7112)。

0.4.23:命名索引体系([[tool.uv.index]]

0.4.23 引入了对包索引定义的重构,作为 pip 风格 --index-url/--extra-index-url 的替代方案。变更日志给出了完整配置示例,这里原样保留:

pyproject.toml 中定义命名索引:

[[tool.uv.index]]
name = "pytorch"
url = "https://download.pytorch.org/whl/cpu"

通过 tool.uv.sources 把特定包固定到指定索引,确保 torch 总是从 pytorch 索引安装:

[tool.uv.sources]
torch = { index = "pytorch" }

[[tool.uv.index]]
name = "pytorch"
url = "https://download.pytorch.org/whl/cpu"

把索引标记为 explicit = true 后,除非显式绑定,否则任何包都不会从该索引安装(torchpytorch 索引、其余包走默认索引):

[tool.uv.sources]
torch = { index = "pytorch" }

[[tool.uv.index]]
name = "pytorch"
url = "https://download.pytorch.org/whl/cpu"
explicit = true

pyproject.toml 之外的索引通过 --index 命令行参数(或 UV_INDEX 环境变量)定义;替换默认索引(PyPI)则用 --default-index(或 UV_DEFAULT_INDEX)。变更日志明确:这些变更与已弃用的 --index-url/--extra-index-url 完全向后兼容,后者行为不变。

配套增强包括:uv add --index/--default-index 会把索引 URL 写入项目(PR #7746);tool.uv.sources 允许一个包绑定多个索引(PR #7769);命名索引支持环境变量认证(PR #7741);--index--default-index 的命名值可被 tool.uv.sources 引用(PR #7910)。

后续加固(0.4.24–0.4.26)

命名索引上线后立刻经历了一轮安全与健壮性修复:

  • 0.4.24(安全相关):从锁文件来源中隐去索引凭证(PR #8307);按文档生效 UV_INDEX_ 而非 UV_HTTP_BASIC_ 认证变量(PR #8306);改进 sources 反序列化错误信息(PR #8308)。
  • 0.4.25:允许自定义索引名包含连字符与下划线(PR #8339);uv.lock 中的索引来源做凭证脱敏(PR #8333);认证缓存的用户名不再被忽略(PR #8345)。
  • 0.4.26:提供凭证时不重写 [[tool.uv.index]] 条目(PR #8502);索引认证变量名把连字符替换为下划线(PR #8452)。

从源码结构看,索引的认证与配置分别落在 crates/uv-auth/src/index.rscrates/uv-distribution-types/src/index.rs 中的 Index 定义,认证细节可进一步参阅 docs/concepts/authentication 目录。

0.4.27:PEP 735 依赖组(dependency-groups

0.4.27 实现了对 PEP 735 标准 [dependency-groups] 表的支持。其语义是:声明不会随包元数据发布的可选依赖组(区别于 [project.optional-dependencies],后者是发布到包元数据中的 extras)。uv 在整个接口中引入了 --group--only-group--no-group 三个新选项。

变更日志说明了兼容策略,值得逐条理解:

  • 此前 uv 用单一的 tool.uv.dev-dependencies 列表声明开发依赖;现在可以按标准格式声明,并把开发依赖拆分为多个组;
  • 对不需要多组的用户,uv 特判名为 dev 的组dev 组等价于 tool.uv.dev-dependencies,后者的内容会被合并进 dev 组参与解析;
  • --dev--only-dev--no-dev 保留为对应 --group 选项的别名;
  • tool.uv.dev-dependencies 在本版本继续支持,未来版本会显示弃用警告;
  • uv 默认同步 dev 组(与旧行为一致),默认组集合可用 tool.uv.default-groups 设置修改。

源码印证:DependencyGroups 解析器

crates/uv-configuration/src/dependency_groups.rs 中的 DependencyGroups 结构实现了上述语义的收敛逻辑。from_history 方法先把 --dev 系列标志"脱糖"为 dev 组的 include/only/exclude 操作,再合并 --group/--only-group/默认组列表;其中两个关键规则与文档表述一一对应:

  • exclude 永远胜过 include(结构体注释:exclude always wins over include);
  • --only 隐含 --no-default-groupslet default_groups = !no_default_groups && !only_groups;),即一旦指定 --only-group,默认组(含 dev)不再自动加入。

同期增强还包括:uv lock --dry-run(PR #7783)与强制锁文件 schema 版本(PR #8509,为后续锁文件演进预留版本约束);0.4.28 又恢复了 dev-dependenciesrequires-dev 的锁文件兼容读取(PR #8599),并在 uv export 中尊重依赖组标记(0.4.29,PR #8659);0.4.30 则修复了非根 workspace 成员定义 --group 时的误报(PR #8734)与 workspace 锁定时纳入成员组(PR #8736)。

uv publish 与 Trusted Publishing(0.4.16 起)

0.4.16 实现了 uv publish 命令(PR #7475)及 Trusted Publishing 支持(PR #7548),随后持续完善:

  • 0.4.21:HTTP/2 请求启用(PR #8049)——发布大文件时受益明显;
  • 0.4.22uv publish 支持交互式输入(PR #8158);缺失用户名时的专用错误(PR #8045);使用原始文件名(PR #8204);
  • 0.4.26uv publish 尊重 --allow-insecure-host(PR #8440);构建失败帮助页(PR #8286);
  • 0.4.28:改进 Trusted Publishing 错误信息,并在缺少权限时给出提示(PR #8632、PR #8633);
  • 0.4.30uv publish --check-url 在上传前检查远端是否已存在该发行版(PR #8531),配合 --skip-existing 使用(PR #8803)。

0.4.18 的文档条目显示官方文档已从 twine 切换到 uv publish 作为发布示例,0.4.17 起 uv builduv publish 也进入了特性总览页——从仓库文档看可参阅 docs/getting-started/features.md

环境变量配置面:0.4 周期新增项一览

0.4 周期把大量命令行开关镜像为环境变量,便于 CI 与全局配置。按版本归纳:

环境变量 引入版本 作用
UV_PROJECT_ENVIRONMENT 0.4.4 自定义项目虚拟环境路径(PR #6834);文档见 0.4.4 的 PR #6987
UV_NO_SYNC 0.4.18 跳过自动同步(PR #7752)
UV_FIND_LINKS 0.4.19 --find-links 的环境变量形式,值用逗号分隔(0.4.21 修复为 CSV,PR #8061)
UV_INDEX / UV_DEFAULT_INDEX 0.4.23 命名索引的 CLI 镜像参数 --index/--default-index 的环境变量形式
UV_FROZEN / UV_LOCKED 0.4.25 --frozen/--locked 的环境变量形式(PR #8340)
UV_INSECURE_HOST 通配符 0.4.21 支持通配主机(PR #8052)
禁用进度输出 0.4.28 无进度条环境(PR #8600)

UV_PROJECT_ENVIRONMENT 的行为在测试中有明确约束:crates/uv/tests/python/venv.rs 验证了 uv venv 在非项目上下文中忽略该变量,而在项目命令中它会改变环境路径(对应 0.4.4 "提示 VIRTUAL_ENV 已设置但项目命令中不会生效"的警告改进,PR #6864)。系统级 uv.toml 配置的支持则晚到 0.4.26 才落地(PR #7851),使团队可以在机器层面统一索引、镜像等设置,配合 docs/concepts/configuration-files.md 的层级规则使用。

Python 版本管理:3.13 与 free-threaded 构建

0.4 周期完整覆盖了 CPython 3.13 的生命周期:

  • 0.4.9:纳入托管 Python 3.13(PR #7263),并升级所有托管 CPython 至最新 patch;
  • 0.4.19:新增 CPython 3.13.0rc3 与 3.12.7 托管下载(PR #7880);
  • 0.4.20:CPython 3.13.0 正式版纳入托管下载,并成为 uv python install 的默认版本(PR #8010);
  • 0.4.16 / 0.4.21 / 0.4.28:free-threaded(无 GIL)Python 从"允许请求解释器"(PR #7431)发展到"托管安装"(PR #8100)再到"+freethreaded 后缀请求特定构建"(PR #8645),且 0.4.22 起优先选用 free-threaded 的 lto 优化构建(PR #8515 在 0.4.27 修正)。

同周期的解释器发现与兼容性子改进包括:0.4.1 直接用 Windows 注册表发现 Python(PR #6761);0.4.2 对 Python 与 PEP 723 脚本不兼容时给出警告(PR #6884);0.4.17 不再在解释器发现阶段生成字节码文件(PR #7707);0.4.29 增加 riscv64 平台标签(PR #8660)并修复 ARM 上 managed Python 的 hard/soft float libc 检测(PR #8498)。

uv run 与 PEP 723 脚本能力的持续扩展

uv run 在 0.4 周期吸收了多个"把 Python 跑起来"的长尾场景:

  • 0.4.2:支持运行 .pyc 文件(PR #6886);
  • 0.4.9--no-sync(PR #7192);
  • 0.4.10:支持直接运行 Python 包(__main__.py,PR #7281)与 zip 应用(PR #7289);
  • 0.4.18uv run -m foo 运行模块(PR #7754);
  • 0.4.19--script 强制按 PEP 723 处理任意扩展名输入(PR #7739);
  • 0.4.21:PEP 723 元数据支持 uv run -(stdin,PR #8111);远程 https:// 脚本直接运行(PR #6375);--with 支持逗号分隔多包(PR #7909);
  • 0.4.30.env 与自定义 env 文件支持(PR #8811);--all-packages 用于 uv run/uv sync/uv export,把 workspace 所有包纳入环境(PR #8742 等);--frozen 可与 --all-packages 联用(PR #8760)。

与运行相关的错误处理也在持续改善:0.4.5 让 uv run 正确透传退出码(PR #6994);0.4.16 在未指定命令时列出可用脚本(0.4.20,PR #7687);0.4.16 新增 --project 参数从指定项目目录运行命令(PR #7603)。

缓存、锁文件与解析器可靠性

变更日志中"Bug fixes"与"Performance"章节密度很高,反映 uv 对缓存与锁正确性的持续投入,摘选具有长期影响的条目:

  • 缓存:0.4.4 避免对缓存目录做规范化(PR #6949);0.4.7 uv cache prune 清理未用 sdist(PR #7112);0.4.8 动态缓存键支持 glob 匹配并换用 globwalk(PR #7337);0.4.13 对损坏 rkyv 条目的 uv cache prune 健壮性(PR #7561);0.4.13 提升 wheel/sdist 缓存版本并对缺失 sdist 的缓存条目自愈(PR #7560、PR #7559);0.4.25 缓存版本化改为向后兼容模式(PR #8386)。
  • 锁文件正确性:0.4.3 下所有 Python 兼容性比较统一为下界语义(PR #6882);0.4.5 剪除不可达包与 wheel(PR #6959、PR #6961);0.4.6 成员版本变化时失效锁文件(PR #7102)、direct URL 来源去除 fragment(PR #7061);0.4.11 --no-sources 调用中纳入 dev-dependencies(PR #7408);0.4.14 回退了 0.4.13 中"无效平台比无效 Python 更兼容"的判定(0.4.15,PR #7608)——这类回退说明解析器平台兼容策略在该周期内经历了反复校准。
  • pyproject.toml 写入安全:0.4.5 起 Ctrl-C(PR #7024)乃至所有错误(PR #7022)都会回滚 pyproject.toml 的修改;0.4.9 避免在非添加编辑中更新偏移量(PR #7262);0.4.25 保持注释位置正确(PR #8384)。
  • 性能:0.4.7 --no-depspip sync 跳过元数据获取(PR #7127);0.4.8 未优化注册表不做批量预取(PR #7226);0.4.21 锁满足性检查使用共享索引、addlock 共享 resolver 状态避免二次 Git 更新(PR #8147、PR #8146)。
  • 并发:0.4.1 修复多个 uv 进程竞争资源锁时的死锁(PR #6790);0.4.13 把"等待获取锁"从用户级警告降级(PR #7502)。

升级路径提示

从变更日志中可以归纳出 0.4 周期需要留意的升级注意点:

  1. 0.4.0 的打包语义反转:如果你的项目此前依赖"无 [build-system] 时默认用 setuptools 打包"的行为,升级后需显式在 [tool.uv] 中设置 package = true;反之,应用类项目可以移除 [build-system] 获得 virtual 行为。
  2. 0.4.14 的 uvx 补全变更uvx 的 shell 补全入口移动到 uvx --generate-shell-completion,这是 0.4.x 中唯一标注为 Breaking 的条目。
  3. 0.4.27 的依赖组迁移tool.uv.dev-dependencies 仍可工作,但新代码建议改用 [dependency-groups]dev 组,并按需拆分多组;默认组用 tool.uv.default-groups 调整。
  4. 0.4.23 的索引迁移--index-url/--extra-index-url 继续可用但已弃用,新项目建议直接使用 [[tool.uv.index]] + tool.uv.sources 的显式绑定,尤其是存在多个专用索引(如 PyTorch)的场景。

小结

0.4.x 周期(0.4.0–0.4.30)完成了 uv 项目模型从"一切皆包"到"应用与库分治"的重构,落地了 uv builduv publish 补齐本地构建-发布闭环,并以命名索引和 PEP 735 依赖组两个标准化能力对齐了上游生态。完整的逐版本条目、PR 编号与修复细节可查阅 changelogs/0.4.x.md;周边版本线的演进可对照 changelogs/0.3.x.mdchangelogs/0.5.x.md。实现层面的深入阅读可从 crates/uv-workspace/src/pyproject.rs(项目/包判定)、crates/uv-configuration/src/dependency_groups.rs(依赖组解析)与 docs/concepts/indexes.md(索引概念)切入。

登录后查看全文
热门项目推荐
相关项目推荐