跳到内容

锁定环境

所谓“锁定”,就是获取一个依赖项(例如 ruff),并将其实际使用的确切版本写入文件中。当处理大量依赖项时,锁定确切版本非常有用,这样可以确保环境是可复现的。如果不进行锁定,依赖项的版本可能会随时间推移、使用不同工具或跨平台时发生变化。

锁定依赖需求

uv 允许以 requirements.txt 格式锁定依赖项。推荐使用标准的 pyproject.toml 来定义依赖项,但也支持其他依赖项格式。有关如何定义依赖项的更多详细信息,请参阅关于声明依赖项的文档。

若要锁定 pyproject.toml 中声明的依赖项:

$ uv pip compile pyproject.toml -o requirements.txt

注意:默认情况下,uv pip compile 的输出仅会显示在屏幕上,若要写入文件,需要使用 --output-file / -o 参数。

若要锁定 requirements.in 中声明的依赖项:

$ uv pip compile requirements.in -o requirements.txt

若要锁定多个文件中声明的依赖项:

$ uv pip compile pyproject.toml requirements-dev.in -o requirements-dev.txt

uv 还支持传统的 setup.pysetup.cfg 格式。若要锁定 setup.py 中声明的依赖项:

$ uv pip compile setup.py -o requirements.txt

若要从标准输入(stdin)锁定依赖项,请使用 -

$ echo "ruff" | uv pip compile -

若要在启用可选依赖项(例如 "foo" 额外项)的情况下进行锁定:

$ uv pip compile pyproject.toml --extra foo

若要在启用所有可选依赖项的情况下进行锁定:

$ uv pip compile pyproject.toml --all-extras

注意:requirements.in 格式不支持额外项(extras)。

若要锁定当前项目目录 pyproject.toml 中的依赖组(例如 foo 组):

$ uv pip compile --group foo

重要

虽然 pip-tools 的 pip compile 目前仍需要添加 --group 标志,但他们正在考虑这一特性。我们期望支持他们最终采用的任何语法和语义。

若要指定应从中获取依赖组的特定项目目录:

$ uv pip compile --project some/path/ --group foo --group bar

或者,您可以为每个组指定 pyproject.toml 的路径:

$ uv pip compile --group some/path/pyproject.toml:foo --group other/pyproject.toml:bar

注意

--group 标志不适用于其他指定的源。例如,uv pip compile some/path/pyproject.toml --group foo 会从 ./pyproject.toml 中获取 foo 组,而不是some/path/pyproject.toml 中获取。

升级依赖需求

当使用输出文件时,uv 会考虑现有输出文件中已固定的版本。如果一个依赖项已被固定,它在随后的编译运行中将不会被升级。例如:

$ echo "ruff==0.3.0" > requirements.txt
$ echo "ruff" | uv pip compile - -o requirements.txt
# This file was autogenerated by uv via the following command:
#    uv pip compile - -o requirements.txt
ruff==0.3.0

若要升级某个依赖项,请使用 --upgrade-package 标志:

$ uv pip compile - -o requirements.txt --upgrade-package ruff

若要升级所有依赖项,可以使用 --upgrade 标志。

同步环境

可以使用 uv pip install 直接从定义文件或已编译的 requirements.txt 文件中安装依赖项。有关更多详细信息,请参阅关于从文件安装包的文档。

使用 uv pip install 安装时,除非已安装的包与锁定文件冲突,否则不会被移除。这意味着环境中可能存在未在锁定文件中声明的依赖项,这对于可复现性并不理想。若要确保环境与锁定文件完全匹配,请改用 uv pip sync

若要使用 requirements.txt 文件同步环境:

$ uv pip sync requirements.txt

若要使用 PEP 751 pylock.toml 文件同步环境:

$ uv pip sync pylock.toml

添加约束

约束文件(Constraints files)类似于 requirements.txt,但它们仅控制已安装需求项的版本。然而,在约束文件中包含某个包并不会触发该包的安装。约束可用于为非当前项目依赖项的包添加版本边界。

若要定义约束,请为包定义一个边界:

constraints.txt
pydantic<2.0

若要使用约束文件:

$ uv pip compile requirements.in --constraint constraints.txt

注意:每个文件中可以定义多个约束,也可以使用多个文件。

uv 还会读取工作区根目录下的 pyproject.toml 中的 constraint-dependencies,并将它们附加到约束文件中指定的约束之后。

添加构建约束

类似于 constraints,但专门针对构建时依赖项,包括构建运行时依赖项时所需的依赖项。

构建约束文件是类似于 requirements.txt 的文件,仅控制构建时需求项的版本。然而,在构建约束文件中包含某个包并不会触发其在构建时的安装;相反,约束仅在包被作为直接或传递性构建时依赖项时生效。构建约束可用于为未明确声明为当前项目构建时依赖项的依赖项添加边界。

例如,如果一个包定义其构建依赖项如下:

pyproject.toml
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

构建约束可用于确保工作区中的每个包都使用特定版本的 setuptools

build-constraints.txt
setuptools==75.0.0

uv 还会读取工作区根目录下的 pyproject.toml 中的 build-constraint-dependencies,并将它们附加到构建约束文件中指定的约束之后。

覆盖依赖版本

覆盖文件(Overrides files)是类似于 requirements.txt 的文件,它们强制安装特定版本的需求项,而不考虑任何组成包所声明的需求,也不考虑这是否会被视为无效的解析。

虽然约束是累加的(它们与组成包的需求相结合),但覆盖是绝对的(它们会完全替换组成包的需求)。

覆盖最常用于移除传递性依赖项的上界。例如,如果 a 需要 c>=1.0,<2.0,而 b 需要 c>=2.0,且当前项目同时需要 ab,那么这些依赖项将无法解析。

若要定义覆盖,请为有问题的包定义新的需求:

overrides.txt
c>=2.0

若要使用覆盖文件:

$ uv pip compile requirements.in --override overrides.txt

现在,解析可以成功了。然而请注意,如果 a 确实不支持 c>=2.0,那么在使用这些包时很可能会遇到运行时错误。

注意:每个文件中可以定义多个覆盖,也可以使用多个文件。