锁定环境
锁定是指针对某个依赖项(例如 ruff
),将确切的使用版本写入文件。在处理众多依赖项时,锁定确切版本非常有用,这样可以重现环境。如果不进行锁定,依赖项的版本可能会随着时间推移、使用不同工具或跨平台而发生变化。
锁定需求
uv 允许以 requirements.txt
格式锁定依赖项。建议使用标准的 pyproject.toml
来定义依赖项,但也支持其他依赖格式。有关如何定义依赖项的更多详细信息,请参阅声明依赖项文档。
要锁定 pyproject.toml
中声明的依赖项:
请注意,默认情况下,uv pip compile
的输出仅显示,需要使用 --output-file
/ -o
参数将其写入文件。
要锁定 requirements.in
中声明的依赖项:
要锁定多个文件中声明的依赖项:
uv 还支持传统的 setup.py
和 setup.cfg
格式。要锁定 setup.py
中声明的依赖项:
要从标准输入锁定依赖项,使用 -
:
要启用可选依赖项进行锁定,例如 “foo” 额外项:
要启用所有可选依赖项进行锁定:
请注意,requirements.in
格式不支持额外项。
要锁定当前项目目录的 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
# 此文件由 uv 通过以下命令自动生成:
# 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
,那么在使用这些包时可能会遇到运行时错误。
请注意,每个文件中可以定义多个覆盖,并且可以使用多个文件。