锁定环境
锁定是指获取一个依赖项(例如 ruff
),并将其确切版本写入文件。当处理许多依赖项时,锁定确切版本非常有用,这样可以复现环境。如果不进行锁定,依赖项的版本可能会随着时间的推移、使用不同的工具或跨平台而发生变化。
锁定需求
uv 允许以 requirements.txt
格式锁定依赖项。建议使用标准的 pyproject.toml
来定义依赖项,但也支持其他依赖项格式。有关如何定义依赖项的更多详细信息,请参阅声明依赖项的文档。
要锁定在 pyproject.toml
中声明的依赖项:
请注意,默认情况下,uv pip compile
的输出仅显示在终端,需要使用 --output-file
/ -o
参数才能写入文件。
要锁定在 requirements.in
中声明的依赖项:
要锁定在多个文件中声明的依赖项:
uv 还支持旧版的 setup.py
和 setup.cfg
格式。要锁定在 setup.py
中声明的依赖项:
要从标准输入锁定依赖项,请使用 -
:
要锁定并启用可选依赖项,例如 "foo" extra:
要锁定并启用所有可选依赖项:
请注意,requirements.in
格式不支持 extras。
要锁定当前项目目录 pyproject.toml
中的依赖项组,例如 foo
组:
Important
pip-tools 的 pip compile
需要添加一个 --group
标志,尽管他们正在考虑这样做。我们期望支持他们采用的任何语法和语义。
要指定从中获取组的项目目录:
或者,您可以为每个组指定一个 pyproject.toml
的路径:
Note
--group
标志不适用于其他指定的源。例如,uv pip compile some/path/pyproject.toml --group foo
从 ./pyproject.toml
而不是 some/path/pyproject.toml
中获取 foo
。
升级需求
使用输出文件时,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
标志:
要升级所有依赖项,可以使用 --upgrade
标志。
同步环境
可以使用 uv pip install
直接从其定义文件或从已编译的 requirements.txt
文件安装依赖项。有关更多详细信息,请参阅从文件安装包的文档。
使用 uv pip install
安装时,除非与锁定文件冲突,否则不会删除已安装的包。这意味着环境中可能存在未在锁定文件中声明的依赖项,这对于可复现性不是很好。为确保环境与锁定文件完全匹配,请改用 uv pip sync
。
要将环境与 requirements.txt
文件同步:
要将环境与 pyproject.toml
文件同步:
添加约束
约束文件是类似 requirements.txt
的文件,仅控制所安装需求的版本。但是,在约束文件中包含包不会触发该包的安装。约束可用于为当前项目非依赖项的依赖项添加边界。
要定义约束,请为包定义一个边界:
要使用约束文件:
请注意,每个文件中可以定义多个约束,并且可以使用多个文件。
uv 还会从工作区根目录的 pyproject.toml
中读取 constraint-dependencies
,并将其附加到约束文件中指定的那些依赖项。
添加构建约束
类似于 constraints
,但专门用于构建时依赖项,包括构建运行时依赖项时所需的那些。
构建约束文件是类似 requirements.txt
的文件,仅控制构建时需求的版本。但是,在构建约束文件中包含包不会在构建时触发其安装;相反,约束仅在包作为直接或传递构建时依赖项需要时才适用。构建约束可用于为当前项目中未明确声明为构建时依赖项的依赖项添加边界。
例如,如果一个包按如下方式定义其构建依赖项:
可以使用构建约束来确保工作区中的每个包都使用特定版本的 setuptools
:
uv 还会从工作区根目录的 pyproject.toml
中读取 build-constraint-dependencies
,并将其附加到构建约束文件中指定的那些依赖项。
覆盖依赖项版本
覆盖文件是类似 requirements.txt
的文件,它强制安装特定版本的需求,而不管任何组成包声明的需求,也不管这是否被视为无效的解析。
虽然约束是附加的,因为它们与组成包的需求相结合,但覆盖是绝对的,因为它们完全取代了组成包的需求。
覆盖最常用于从传递依赖项中删除上限。例如,如果 a
需要 c>=1.0,<2.0
,b
需要 c>=2.0
,而当前项目需要 a
和 b
,那么依赖项就无法解析。
要定义覆盖,请为有问题的包定义新的需求:
要使用覆盖文件:
现在,解析可以成功。但是,请注意,如果 a
是正确的,即它不支持 c>=2.0
,那么在使用这些包时可能会遇到运行时错误。
请注意,每个文件中可以定义多个覆盖,并且可以使用多个文件。