一组命令行工具可帮助您使基于pip
的包保持最新状态,即使您已固定它们也是如此。你确实把它们钉住了,对吧? (在构建 Python 应用程序及其生产依赖项时,您需要确保构建是可预测的和确定性的。)
与pip
类似, pip-tools
必须安装在项目的每个虚拟环境中:
$ source /path/to/venv/bin/activate
(venv) $ python -m pip install pip-tools
注意:所有剩余的示例命令都假设您已经激活了项目的虚拟环境。
pip-compile
的用法示例pip-compile
命令允许您从pyproject.toml
、 setup.cfg
、 setup.py
或requirements.in
中指定的依赖项编译requirements.txt
文件。
使用pip-compile
或python -m piptools compile
运行它(或者pipx run --spec pip-tools pip-compile
如果pipx
是使用适当的 Python 版本安装的)。如果您使用多个Python版本,还可以在Windows上运行py -XY -m piptools compile
在其他系统上运行pythonX.Y -m piptools compile
。
pip-compile
应在与您的项目相同的虚拟环境中运行,因此需要特定 Python 版本或其他环境标记的条件依赖项将相对于您的项目环境进行解析。
注意:如果pip-compile
找到满足依赖关系的现有requirements.txt
文件,则即使有可用更新,也不会进行任何更改。要从头开始编译,请首先删除现有的requirements.txt
文件,或参阅更新需求以获取替代方法。
pyproject.toml
的要求pyproject.toml
文件是配置包和应用程序的最新标准,建议用于新项目。 pip-compile
支持安装project.dependencies
和project.optional-dependencies
。由于这是一个官方标准,您可以使用pip-compile
来固定使用符合现代标准的打包工具(如 Setuptools、Hatch 或 flit)的项目中的依赖项。
假设您有一个使用Setuptools
打包的“foobar”Python 应用程序,并且您希望将其固定用于生产。您可以将项目元数据声明为:
[ build-system ]
requires = [ " setuptools " , " setuptools-scm " ]
build-backend = " setuptools.build_meta "
[ project ]
requires-python = " >=3.9 "
name = " foobar "
dynamic = [ " dependencies " , " optional-dependencies " ]
[ tool . setuptools . dynamic ]
dependencies = { file = [ " requirements.in " ] }
optional-dependencies.test = { file = [ " requirements-test.txt " ] }
如果您有一个使用Hatch
打包的 Django 应用程序,并且您希望将其固定用于生产。您还希望将开发工具固定在单独的 pin 文件中。您将django
声明为依赖项并创建一个包含pytest
可选依赖项dev
:
[ build-system ]
requires = [ " hatchling " ]
build-backend = " hatchling.build "
[ project ]
name = " my-cool-django-app "
version = " 42 "
dependencies = [ " django " ]
[ project . optional-dependencies ]
dev = [ " pytest " ]
您可以轻松生成 PIN 文件,如下所示:
$ pip-compile -o requirements.txt pyproject.toml
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
# pip-compile --output-file=requirements.txt pyproject.toml
#
asgiref==3.6.0
# via django
django==4.1.7
# via my-cool-django-app (pyproject.toml)
sqlparse==0.4.3
# via django
$ pip-compile --extra dev -o dev-requirements.txt pyproject.toml
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
# pip-compile --extra=dev --output-file=dev-requirements.txt pyproject.toml
#
asgiref==3.6.0
# via django
attrs==22.2.0
# via pytest
django==4.1.7
# via my-cool-django-app (pyproject.toml)
exceptiongroup==1.1.1
# via pytest
iniconfig==2.0.0
# via pytest
packaging==23.0
# via pytest
pluggy==1.0.0
# via pytest
pytest==7.2.2
# via my-cool-django-app (pyproject.toml)
sqlparse==0.4.3
# via django
tomli==2.0.1
# via pytest
这对于固定应用程序非常有用,而且还可以保持开源 Python 包的 CI 稳定。
setup.py
和setup.cfg
的要求pip-compile
还完全支持使用setuptools
的基于setup.py
和setup.cfg
的项目。
只需像往常一样定义您的依赖项和附加项,然后按上述方式运行pip-compile
即可。
requirements.in
的需求您还可以根据您的要求使用纯文本文件(例如,如果您不希望您的应用程序成为一个包)。要使用requirements.in
文件声明Django依赖项:
# requirements.in
django
现在,运行pip-compile requirements.in
:
$ pip-compile requirements.in
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
# pip-compile requirements.in
#
asgiref==3.6.0
# via django
django==4.1.7
# via -r requirements.in
sqlparse==0.4.3
# via django
它将生成您的requirements.txt
,其中固定了所有Django 依赖项(以及所有底层依赖项)。
(更新需求)=
pip-compile
使用满足您在支持的文件中指定的依赖项的最新版本生成requirements.txt
文件。
如果pip-compile
找到满足依赖关系的现有requirements.txt
文件,则即使有可用更新,也不会进行任何更改。
要强制pip-compile
更新现有requirements.txt
中的所有包,请运行pip-compile --upgrade
。
要将特定包更新到最新版本或特定版本,请使用--upgrade-package
或-P
标志:
# only update the django package
$ pip-compile --upgrade-package django
# update both the django and requests packages
$ pip-compile --upgrade-package django --upgrade-package requests
# update the django package to the latest, and requests to v2.0.0
$ pip-compile --upgrade-package django --upgrade-package requests==2.0.0
您可以将--upgrade
和--upgrade-package
组合在一个命令中,以对允许的升级提供限制。例如,升级所有软件包,同时将请求限制为低于 3.0 的最新版本:
$ pip-compile --upgrade --upgrade-package ' requests<3.0 '
如果您想使用pip
自 8.0 版本以来提供的哈希检查模式, pip-compile
提供--generate-hashes
标志:
$ pip-compile --generate-hashes requirements.in
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
# pip-compile --generate-hashes requirements.in
#
asgiref==3.6.0
--hash=sha256:71e68008da809b957b7ee4b43dbccff33d1b23519fb8344e33f049897077afac
--hash=sha256:9567dfe7bd8d3c8c892227827c41cce860b368104c3431da67a0c5a65a949506
# via django
django==4.1.7
--hash=sha256:44f714b81c5f190d9d2ddad01a532fe502fa01c4cb8faf1d081f4264ed15dcd8
--hash=sha256:f2f431e75adc40039ace496ad3b9f17227022e8b11566f4b363da44c7e44761e
# via -r requirements.in
sqlparse==0.4.3
--hash=sha256:0323c0ec29cd52bceabc1b4d9d579e311f3e4961b98d174201d5622a23b85e34
--hash=sha256:69ca804846bb114d2ec380e4360a8a340db83f0ccf3afceeb1404df028f57268
# via django
要将固定需求输出到requirements.txt
以外的文件名中,请使用--output-file
。这对于编译多个文件可能很有用,例如对 django 使用不同的约束来使用 tox 测试具有两个版本的库:
$ pip-compile --upgrade-package ' django<1.0 ' --output-file requirements-django0x.txt
$ pip-compile --upgrade-package ' django<2.0 ' --output-file requirements-django1x.txt
或者要输出到标准输出,请使用--output-file=-
:
$ pip-compile --output-file=- > requirements.txt
$ pip-compile - --output-file=- < requirements.in > requirements.txt
pip
任何有效的pip
标志或参数都可以通过pip-compile
的--pip-args
选项传递,例如
$ pip-compile requirements.in --pip-args " --retries 10 --timeout 30 "
您可以通过将pip-compile
和pip-sync
的项目级默认值(如果从 stdin 进行管道输入,则为当前工作目录)。默认情况下, pip-compile
和pip-sync
都会首先查找.pip-tools.toml
文件,然后查找pyproject.toml
。您还可以使用--config
选项指定备用 TOML 配置文件。
可以指定全局配置值和特定于命令的配置值。例如,要默认在生成的需求文件输出中生成pip
哈希,您可以在配置文件中指定:
[ tool . pip-tools ]
generate-hashes = true
可能多次使用的pip-compile
和pip-sync
选项必须定义为配置文件中的列表,即使它们只有一个值。
pip-tools
支持其子命令的所有有效命令行标志的默认值。配置键可以包含下划线而不是破折号,因此上面也可以用这种格式指定:
[ tool . pip-tools ]
generate_hashes = true
特定于pip-compile
和pip-sync
的配置默认值可以放在单独的部分下。例如,默认情况下使用pip-compile
执行试运行:
[ tool . pip-tools . compile ] # "sync" for pip-sync
dry-run = true
这不会影响pip-sync
命令,该命令也有一个--dry-run
选项。请注意,每当声明两者时,本地设置优先于同名的全局设置,因此这也会使pip-compile
生成哈希值,但丢弃全局试运行设置:
[ tool . pip-tools ]
generate-hashes = true
dry-run = true
[ tool . pip-tools . compile ]
dry-run = false
您可能将pip-compile
命令包装在另一个脚本中。为了避免自定义脚本的使用者感到困惑,您可以通过设置CUSTOM_COMPILE_COMMAND
环境变量来覆盖在需求文件顶部生成的更新命令。
$ CUSTOM_COMPILE_COMMAND= " ./pipcompilewrapper " pip-compile requirements.in
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
# ./pipcompilewrapper
#
asgiref==3.6.0
# via django
django==4.1.7
# via -r requirements.in
sqlparse==0.4.3
# via django
如果您有不同的环境,需要安装不同但兼容的软件包,那么您可以创建分层需求文件并使用一层来约束另一层。
例如,如果您有一个 Django 项目,您希望在生产环境中使用最新的2.1
版本,并且在开发时希望使用 Django 调试工具栏,那么您可以创建两个*.in
文件,每一层一个:
# requirements.in
django<2.2
在开发需求dev-requirements.in
的顶部,您可以使用-c requirements.txt
将开发需求限制为在requirements.txt
中已选择用于生产的包。
# dev-requirements.in
-c requirements.txt
django-debug-toolbar<2.2
首先,照常编译requirements.txt
:
$ pip-compile
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
# pip-compile
#
django==2.1.15
# via -r requirements.in
pytz==2023.3
# via django
现在编译开发需求,并使用requirements.txt
文件作为约束:
$ pip-compile dev-requirements.in
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
# pip-compile dev-requirements.in
#
django==2.1.15
# via
# -c requirements.txt
# django-debug-toolbar
django-debug-toolbar==2.1
# via -r dev-requirements.in
pytz==2023.3
# via
# -c requirements.txt
# django
sqlparse==0.4.3
# via django-debug-toolbar
正如您在上面看到的,尽管 Django 2.2
版本可用,但开发要求仅包括 Django 2.1
版本,因为它们受到限制。现在,两个编译的需求文件都可以安全地安装在开发环境中。
要在生产阶段安装需求,请使用:
$ pip-sync
您可以通过以下方式在开发阶段安装需求:
$ pip-sync requirements.txt dev-requirements.txt
您可以使用pip-compile
作为预提交的挂钩。请参阅预提交文档以获取说明。示例.pre-commit-config.yaml
:
repos :
- repo : https://github.com/jazzband/pip-tools
rev : 7.4.1
hooks :
- id : pip-compile
您可能希望通过配置args
和/或files
来自定义pip-compile
args,例如:
repos :
- repo : https://github.com/jazzband/pip-tools
rev : 7.4.1
hooks :
- id : pip-compile
files : ^requirements/production.(in|txt)$
args : [--index-url=https://example.com, requirements/production.in]
如果您有多个需求文件,请确保为每个文件创建一个挂钩。
repos :
- repo : https://github.com/jazzband/pip-tools
rev : 7.4.1
hooks :
- id : pip-compile
name : pip-compile setup.py
files : ^(setup.py|requirements.txt)$
- id : pip-compile
name : pip-compile requirements-dev.in
args : [requirements-dev.in]
files : ^requirements-dev.(in|txt)$
- id : pip-compile
name : pip-compile requirements-lint.in
args : [requirements-lint.in]
files : ^requirements-lint.(in|txt)$
- id : pip-compile
name : pip-compile requirements.in
args : [requirements.in]
files : ^requirements.(in|txt)$
pip-sync
的用法示例现在您已经有了requirements.txt
,您可以使用pip-sync
更新您的虚拟环境以准确反映其中的内容。这将安装/升级/卸载匹配requirements.txt
内容所需的一切。
使用pip-sync
或python -m piptools sync
运行它。如果您使用多个Python版本,还可以在Windows上运行py -XY -m piptools sync
,在其他系统上运行pythonX.Y -m piptools sync
。
pip-sync
必须安装到与项目相同的虚拟环境中并运行,以确定要安装或升级的包。
请注意: pip-sync
只能与pip-compile
生成的requirements.txt
一起使用。
$ pip-sync
Uninstalling flake8-2.4.1:
Successfully uninstalled flake8-2.4.1
Collecting click==4.1
Downloading click-4.1-py2.py3-none-any.whl (62kB)
100% |................................| 65kB 1.8MB/s
Found existing installation: click 4.0
Uninstalling click-4.0:
Successfully uninstalled click-4.0
Successfully installed click-4.1
要同步多个*.txt
依赖项列表,只需通过命令行参数传递它们,例如
$ pip-sync dev-requirements.txt requirements.txt
传入空参数将导致其默认为requirements.txt
。
任何有效的pip install
标志或参数都可以通过pip-sync
的--pip-args
选项传递,例如
$ pip-sync requirements.txt --pip-args " --no-cache-dir --no-deps "
注意: pip-sync
不会升级或卸载打包工具,例如setuptools
、 pip
或pip-tools
本身。使用python -m pip install --upgrade
升级这些软件包。
requirements.in
和requirements.txt
提交到源代码管理吗?一般来说,是的。如果您希望从源代码管理中获得可重现的环境安装,那么是的,您应该将requirements.in
和requirements.txt
都提交到源代码管理。
请注意,如果您要在多个 Python 环境上进行部署(请阅读下面的部分),则必须为每个 Python 环境提交单独的输出文件。我们建议使用{env}-requirements.txt
格式(例如: win32-py3.7-requirements.txt
、 macos-py3.10-requirements.txt
等)。
requirements.in
和pip-compile
requirements.txt
跨环境使用包的依赖关系可能会根据安装它的 Python 环境而变化。在这里,我们将Python环境定义为操作系统、Python版本(3.7、3.8等)和Python实现(CPython、PyPy等)的组合。有关准确的定义,请参阅 PEP 508 环境标记的可能组合。
由于每个环境生成的requirements.txt
可能不同,因此用户必须分别在每个Python环境上执行pip-compile
以生成对每个所述环境有效的requirements.txt
。相同的requirements.in
可以用作所有环境的源文件,根据需要使用 PEP 508 环境标记,与常规pip
跨环境使用的方式相同。
如果生成的requirements.txt
对于所有Python环境都保持完全相同,那么它可以跨Python环境安全地使用。但用户应该小心,因为任何包更新都可能引入依赖于环境的依赖项,从而使任何新生成的requirements.txt
也依赖于环境。作为一般规则,建议用户仍应始终在每个目标 Python 环境上执行pip-compile
以避免出现问题。
pip-tools
是一个提高构建可重复性的好工具。但有一些事情需要记住。
pip-compile
在不同的环境中会产生不同的结果。pip
必须与PIP_CONSTRAINT
环境变量一起使用,以锁定构建环境中的依赖项,如 #8439 中所述。继续之前的pyproject.toml
示例,创建单个锁定文件可以如下完成:
$ pip-compile --all-build-deps --all-extras --output-file=constraints.txt --strip-extras pyproject.toml
#
# This file is autogenerated by pip-compile with Python 3.9
# by the following command:
#
# pip-compile --all-build-deps --all-extras --output-file=constraints.txt --strip-extras pyproject.toml
#
asgiref==3.5.2
# via django
attrs==22.1.0
# via pytest
backports-zoneinfo==0.2.1
# via django
django==4.1
# via my-cool-django-app (pyproject.toml)
editables==0.3
# via hatchling
hatchling==1.11.1
# via my-cool-django-app (pyproject.toml::build-system.requires)
iniconfig==1.1.1
# via pytest
packaging==21.3
# via
# hatchling
# pytest
pathspec==0.10.2
# via hatchling
pluggy==1.0.0
# via
# hatchling
# pytest
py==1.11.0
# via pytest
pyparsing==3.0.9
# via packaging
pytest==7.1.2
# via my-cool-django-app (pyproject.toml)
sqlparse==0.4.2
# via django
tomli==2.0.1
# via
# hatchling
# pytest
某些构建后端还可能使用 PEP 517 和 PEP 660 中描述的get_requires_for_build_
挂钩动态请求构建依赖项。这将在输出中使用以下后缀之一进行指示:
(pyproject.toml::build-system.backend::editable)
(pyproject.toml::build-system.backend::sdist)
(pyproject.toml::build-system.backend::wheel)
pip-compile-multi - 用于多个交叉引用需求文件的 pip-compile 命令包装器。
pipdeptree 打印已安装软件包的依赖关系树。
requirements.in
requirements.txt
高亮:
本节列出了当前已弃用的pip-tools
功能。
--allow-unsafe
行为 (#989)。使用--no-allow-unsafe
保留旧行为。建议现在通过--allow-unsafe
来适应即将到来的变化。--resolver=backtracking
。--strip-extras
行为将默认启用(#1613)。使用--no-strip-extras
来保留旧的行为。您可以选择默认回溯解析器或已弃用的旧版解析器。
旧版解析器有时会无法解析依赖项。回溯解析器更强大,但通常需要更长的时间来运行。
您可以继续使用带有--resolver=legacy
的旧解析器,但请注意它已被弃用并将在未来版本中删除。