2.5 构建和发布包

原文链接: https://docs.astral.sh/uv/guides/package/

2.5 构建和发布包

uv 支持通过 uv build 把 Python 包构建为源码分发和二进制分发,并通过 uv publish 把它们上传到仓库。

准备项目

在尝试发布项目之前,你需要确保它已经可以打包分发。

如果你的项目在 pyproject.toml 中没有 [build-system] 定义,uv 在执行项目内的 uv sync 操作时不会构建它,但在 uv build 时会退回使用旧式的 setuptools 构建系统。

注意

使用 uv init 创建的项目默认包含 [build-system] 定义。

我们强烈建议配置构建系统。更多内容请阅读项目配置文档。

构建包

使用 uv build 构建包:

1
$ uv build

默认情况下,uv build 会构建当前目录中的项目,并把构建产物放入 dist/ 子目录。

另外,uv build <SRC> 会构建指定目录中的包,而 uv build --package <PACKAGE> 会构建当前工作区中指定的包。

信息

默认情况下,uv build 在从 pyproject.toml 的 build-system.requires 段落解析构建依赖时会遵循 tool.uv.sources。发布包时,我们建议运行 uv build --no-sources,以确保在 tool.uv.sources 被禁用(例如使用 pypa/build 等其他构建工具时)的情况下包仍能正确构建。

更新版本

uv version 命令为发布前更新包版本提供了便利操作。读取包版本请参阅项目文档。

要更新到精确版本,把它作为位置参数传入:

1
2
$ uv version 1.0.0
hello-world 0.7.0 => 1.0.0

要预览变更而不修改 pyproject.toml,请使用 --dry-run 标志:

1
2
3
4
$ uv version 2.0.0 --dry-run
hello-world 1.0.0 => 2.0.0
$ uv version
hello-world 1.0.0

要按语义化规则递增包版本,请使用 --bump 选项:

1
2
$ uv version --bump minor
hello-world 1.2.3 => 1.3.0

--bump 选项支持以下常见版本组成部分:major、minor、patch、stable、alpha、beta、rc、post 和 dev。多次提供时,各组成部分会按从大到小(从 major 到 dev)的顺序依次应用。

你也可以用 --bump <component>=<value> 提供一个数值,以显式设置结果中该组成部分的值:

1
2
$ uv version --bump patch --bump dev=66463664
hello-world 0.0.1 => 0.0.2.dev66463664

要从稳定版本切换到预发布版本,除了预发布组成部分之外,还需递增 major、minor 或 patch 之一:

1
2
3
4
$ uv version --bump patch --bump beta
hello-world 1.3.0 => 1.3.1b1
$ uv version --bump major --bump alpha
hello-world 1.3.0 => 2.0.0a1

从一个预发布版本切换到新的预发布版本时,只需递增相应的预发布组成部分:

1
2
$ uv version --bump beta
hello-world 1.3.0b1 => 1.3.0b2

从预发布版本切换到稳定版本时,可以用 stable 选项清除预发布组成部分:

1
2
$ uv version --bump stable
hello-world 1.3.1b2 => 1.3.1

信息

默认情况下,uv version 在修改项目后会执行锁定和同步。要阻止锁定和同步,请使用 --frozen;如果只想阻止同步,请使用 --no-sync。

发布包

注意

从 GitHub Actions 发布到 PyPI 的完整指南可在 GitHub 指南中找到。

使用 uv publish 发布包:

1
$ uv publish

用 --token 或 UV_PUBLISH_TOKEN 设置 PyPI 令牌,或者用 --username 或 UV_PUBLISH_USERNAME 设置用户名并用 --password 或 UV_PUBLISH_PASSWORD 设置密码。如果要从 GitHub Actions 或其他 Trusted Publisher 发布到 PyPI,则无需设置任何凭据,只需向 PyPI 项目添加受信发布者。

使用受信发布时,即使发布失败,uv 也会尝试在发布后使短期 PyPI 令牌失效。这进一步缩短了短期令牌的暴露时间(其生命周期本就很短)。

如果失效操作失败,uv 会输出警告,但不会改变发布结果。通过 --token 或 UV_PUBLISH_TOKEN 显式提供的令牌不会被吊销。

注意

PyPI 不再支持用用户名和密码发布,你需要改为生成令牌。使用令牌等价于设置 --username __token__ 并把令牌作为密码。

如果你通过 [[tool.uv.index]] 使用自定义索引,请添加 publish-url 并使用 uv publish --index <name>。例如:

1
2
3
4
5
[[tool.uv.index]]
name = "testpypi"
url = "https://test.pypi.org/simple/"
publish-url = "https://test.pypi.org/legacy/"
explicit = true

注意

使用 uv publish --index <name> 时,pyproject.toml 必须存在,也就是说发布 CI 任务中需要包含检出步骤。

尽管 uv publish 会重试失败的上传,但发布仍可能在中途失败,导致部分文件已上传而部分文件缺失。对于 PyPI,你可以重试完全相同的命令,已存在的相同文件会被忽略。对于其他仓库,请使用 --check-url <index url> 并提供包所属的索引 URL(而不是发布 URL)。使用 --index 时,索引 URL 会被用作检查 URL。uv 会跳过与仓库中文件相同的上传,同时还能处理并发上传的竞态。注意,已存在的文件必须与之前上传到仓库的文件完全一致,这样可以避免意外地为同一版本发布内容不同的源码分发和 wheel。

随包上传证明

注意

某些第三方包索引可能不支持证明,并会拒绝包含证明的上传(而不是静默忽略)。如果上传时遇到问题,可以使用 --no-attestations 或 UV_PUBLISH_NO_ATTESTATIONS 禁用 uv 的默认行为。

提示

uv publish 目前不会生成证明;证明必须在发布之前单独创建。

uv publish 支持向支持证明的仓库(如 PyPI)上传证明。

uv 会自动发现并匹配证明。例如,对于下面的 dist/ 目录,uv publish 会把证明与对应的分发包一起上传:

1
2
3
4
5
$ ls dist/
hello_world-1.0.0-py3-none-any.whl
hello_world-1.0.0-py3-none-any.whl.publish.attestation
hello_world-1.0.0.tar.gz
hello_world-1.0.0.tar.gz.publish.attestation

安装你的包

用 uv run 测试该包能否被安装和导入:

1
$ uv run --with <PACKAGE> --no-project -- python -c "import <PACKAGE>"

--no-project 标志用于避免从本地项目目录安装该包。

提示

如果你最近安装过该包,可能需要加上 --refresh-package <PACKAGE> 选项,以避免使用缓存的包版本。

后续步骤

要进一步了解发布包,请查看 PyPA 关于构建与发布的指南。

或者继续阅读把 uv 与其他软件集成的指南。

最后修改 September 25, 2026: 更新 (221c74c33)