安装新包时如何自动更新需求文件?

How to update a requirements file automatically when new packages are installed?

通过 pip freeze 跟踪虚拟环境的要求很简单。

pip freeze > requirements.txt

但是,目前,每当将新包添加到 venv 时,都需要手动将其添加到需求文件中。为此,我通常只是再次 运行 冻结命令并将其通过管道传输到需求文件中,但有时我会忘记 运行 这个命令,这可能会很麻烦,尤其是在我跨不同位置的存储库中必须记住我需要安装哪些包!

每当在虚拟环境中安装新包时,有没有办法自动更新一个 requirements.txt 文件来自动包含这个新包包裹?

使用 pipenv 而不是 pip。它是一个更好的依赖管理器,将确保最佳实践并消除手动工作。

要了解 pipenv 的使用,请阅读此 article

当只使用普通 pip 安装包时,目前没有办法让它自动生成或更新 requirements.txt 文件。它仍然是使用 pip freeze > requirements.txt.

的手动过程

如果目的是确保安装的包被正确跟踪或注册(即在存储库的版本控制中跟踪),那么您将必须使用 其他 工具“环绕”pip 的功能。

你有两个选择。

选项 1:使用包管理器

有许多 Python 包管理器将“安装包”与“在某处记录已安装的包”相结合。

  • pipenv
    • "它会自动为您的项目创建和管理 virtualenv,以及 adds/removes 来自 Pipfile 的包,就像您 install/uninstall 包一样。它还会生成非常重要的 Pipfile.lock,用于生成确定性构建。
    • 工作流程(参见Example Pipenv Workflow
      $ pipenv install some-package
      
      $ cat Pipfile
      ...
      [packages]
      some-package = "*"
      
      # Commit modified Pipfile and Pipfile.lock
      $ git add Pipfile*
      
      # On some other copy of the repo, install stuff from Pipfile
      $ pipenv install
      
  • poetry
    • "poetry 是一种处理依赖项安装以及构建和打包 Python 包的工具。它只需要一个文件即可完成所有这些工作:新的标准化 pyproject.toml. 也就是说,诗歌用pyproject.toml代替了setup.pyrequirements.txtsetup.cfgMANIFEST.in以及新增的Pipfile.*"
    • 工作流程(参见Basic Usage
      $ poetry add requests
      
      $ cat pyproject.toml
      ...
      [tool.poetry.dependencies]
      requests = "*"
      
      # Commit modified pyproject.toml
      $ git add pyproject.toml
      
      # On some other copy of the repo, install stuff from Pipfile
      $ poetry install
      

选项 2:git 预提交挂钩

这个解决方案不会在“安装包期间”发生,但如果目的是确保您跟踪的“requirements.txt”与您的虚拟环境同步,那么您可以添加一个git pre-commit hook 那:

  1. 生成单独的 requirements_check.txt 文件
  2. 将 requirements_check.txt 与您的 requirements.txt
  3. 进行比较
  4. 如果存在差异则中止提交

示例.git/hooks/pre-commit

#!/usr/local/bin/bash

pip freeze > requirements_check.txt
cmp --silent requirements_check.txt requirements.txt

if [ $? -gt 0 ]; 
then
  echo "There are packages in the env not in requirements.txt"
  echo "Aborting commit"
  rm requirements_check.txt
  exit 1
fi

rm requirements_check.txt
exit 0

输出:

$ git status
...
nothing to commit, working tree clean

$ pip install pydantic

$ git add .
$ git commit
The output of pip freeze is different from requirements.txt
Aborting commit

$ pip freeze > requirements.txt
$ git add .
$ git commit -m "Update requirements.txt"
[master 313b685] Update requirements.txt
 1 file changed, 1 insertion(+)