【问题标题】:How can I use a pip requirements file to uninstall as well as install packages?如何使用 pip 要求文件来卸载和安装软件包?
【发布时间】:2012-10-22 00:49:05
【问题描述】:

我有一个在开发过程中发生变化的 pip 需求文件。

pip 是否可以卸载 未出现在需求文件中的软件包以及安装那些出现的软件包?有标准方法吗?

这将允许 pip 要求文件成为包的规范列表 - 一种“当且仅当”的方法。

更新:我在https://github.com/pypa/pip/issues/716建议它作为一个新功能

【问题讨论】:

  • 你真的想要 pip 卸载任意包,因为你的程序不需要它们吗?听起来有点危险……
  • @ScottHunter 如果你在一个没有站点包的 virtualenv 中,这样做是合理的。
  • @ScottHunter 是的,如果使用受控(虚拟)环境,我想确定那里有什么 - 并且没有其他可能导致问题的存在,例如意外的依赖关系。
  • @MichaelMior 如果这是答案,请添加为答案,我会接受!
  • @wodow 完成。我没有发布作为答案的唯一原因是因为可能有一个更有用的解决方案可以让你得到你想要的。

标签: python pip


【解决方案1】:

这应该卸载任何不在 requirements.txt 中的内容:

pip freeze | grep -v -f requirements.txt - | grep -v '^#' | xargs pip uninstall -y

虽然这不适用于使用-e 安装的软件包,即来自 git 存储库或类似存储库。要跳过这些,只需过滤掉以-e 标志开头的包:

pip freeze | grep -v -f requirements.txt - | grep -v '^#' | grep -v '^-e ' | xargs pip uninstall -y

那么,显然:

pip install -r requirements.txt

2016 年更新: 不过,您可能并不想真正使用上述方法。 Check out pip-tools and pip-sync 以更强大的方式完成您可能希望做的事情。

https://github.com/nvie/pip-tools

2016 年 5 月更新:

您现在也可以使用pip uninstall -r requirements.txt,但这基本上是相反的——它会卸载requirements.txt 中的所有内容

2019 年 5 月更新:

查看pipenvPoetry。包管理领域发生了很多事情,使得这类问题有点过时了。不过,我实际上仍然很乐意使用 pip-tools。

【讨论】:

  • 那太好了。在我看来,如果他们手动在一台主机上安装某些东西而不更新他们的 requirements.txt,则通过破坏一切来强制开发人员明确他们的依赖关系的好方法。我很想知道添加该功能的拉取请求会产生什么样的反馈。
  • 这是正确答案!我把它放在我的 project.config 文件中,用于 Elastic Beanstalk 上的 Django:05_pip_clean: command: "pip freeze | grep -v -f requirements.txt - | grep -v '^#' | xargs pip uninstall -y"。现在我可以通过在requirements.txt 中使用 cmets 来回滚 pip 包而无需重建我的环境。这节省了我真正的停机时间。谢谢!
  • 有没有以 # 开头的 pip freeze 输出?换句话说,第二个 grep 有必要吗?
  • 不确定pip freeze 是否制作了 cmets,但有一天他们可能会将其添加到 API 中,如果他们这样做了,它将是有效的。如果他们不这样做,那么上述内容是无操作的。破折号允许您使用上一个命令中的标准输入,在这种情况下,破折号告诉 grep 将 requirements.txt 的内容与 pip freeze 的输出进行比较(在这种情况下,pip freeze 的输出与标准输入同义)
  • 我强烈推荐 pip-tools。 +1
【解决方案2】:

您现在可以将-r requirements.txt 参数传递给pip uninstall

pip uninstall -r requirements.txt -y

至少截至pip 8.1.2,pip help uninstall 显示:

...
Uninstall Options:
  -r, --requirement <file>    Uninstall all the packages listed in the given requirements file.  This option can be
                              used multiple times.
...

【讨论】:

  • 这不会卸载未出现在文件中的软件包。它会卸载 确实 出现在文件中的软件包。
【解决方案3】:

这不是pip 的功能,不。如果你真的想要这样的东西,你可以编写一个脚本来比较 pip freeze 和你的 requirements.txt 的输出,但这可能比它的价值更麻烦。

使用virtualenv,只需创建一个干净的环境并从requirements.txt(重新)安装,就更容易、更可靠,例如:

deactivate
rm -rf venv/
virtualenv venv/
source venv/bin/activate
pip install -r requirements.txt

【讨论】:

  • 如果某些包(PIL、lxml 等)需要长时间编译,那么卸载不在需求文件中的包可能很有用 - 特别是如果这是在实时服务器上进行的即使用虚拟环境。
  • @melinath 如果它们不在您的需求文件中并且已经安装,那么编译不应该再次发生。
  • @MichaelMior - 除非您按照这个答案的建议擦除整个 virtualenv。
  • @melinath 但是,如果您擦除 virtualenv 并且不需要该软件包(并且不在您的 requirements.txt 中),为什么还要再次安装它?
  • @MichaelMior 我会尝试更明确地陈述我的原始评论。看来你可能误解了我的观点。想象一个包含 PIL 和 lxml 的简单需求文件。但随后您决定不再需要 lxml,并将其从需求文件中删除。如果您按照此答案的建议进行操作并擦除 virtualenv,则必须重新安装(并重新编译)PIL。选择简单地卸载 lxml 会更有效(即所有不在需求文件中的包。)
【解决方案4】:

简短的回答是不,你不能用 pip 做到这一点。

【讨论】:

  • 正如斯蒂芬在下面所说:pip uninstall -r requirements.txt
  • @Ommit 这不会卸载未出现在需求文件中的软件包。它会卸载文件中出现的所有包。
  • @Micheal Mior,啊,我对原始问题的关注不够。我的错。
  • 在@Ommit 的命令中添加-y 以避免多次按Y 和输入。从我的错误中吸取教训。
  • 只需添加:pip uninstall -r requirements.txt 只会卸载您的 requirements.txt 中的版本。例如,如果您卸载boto3==1.10.0,如果您之前安装过pip freeze(或任何旧版本),pip freeze 将显示boto3==1.0.1
【解决方案5】:

这是一个老问题(但很好),自从提出这个问题以来,情况发生了很大变化。

在另一个答案中有对pip-sync 的临时引用,但值得自己回答,因为它恰好解决了 OP 的问题。

pip-syncrequirements.txt 文件作为输入,并“调整”您当前的 Python 环境,使其与requirements.txt 中的内容完全匹配。这包括删除您的环境中存在但requirements.txt 中不存在的任何包。

示例:假设我们希望我们的 env 包含(仅)3 个库:libAlibBlibC,如下所示:

> cat requirements.txt
libA==1.0
libB==1.1
libC==1.2

但我们的环境当前包含libClibD

> pip freeze
libC==1.2
libD==1.3

运行 pip-sync 将导致这个,这是我们想要的最终状态:

> pip-sync requirements.txt
> pip freeze
libA==1.0
libB==1.1
libC==1.2

【讨论】:

  • 当心,如果你有一个全局安装的 pip-tools,它不会在你当前激活的 virtualenv 中卸载......仍然很奇怪,但除此之外,这是我所知道的最直接的需求管理工具。
【解决方案6】:

斯蒂芬的提议是个好主意,但不幸的是它没有奏效 如果您在文件中仅包含直接要求,这听起来 对我来说更干净。

将卸载所有依赖项, 甚至包括distribute,分解pip 本身。

在跟踪虚拟环境的版本时维护干净的需求文件

这是我尝试对我的虚拟环境进行版本跟踪的方法。 我尽量保持最小的requirements.txt,只包括 直接要求,甚至没有提到版本约束 我不确定。

但除此之外,我保留并包含在版本跟踪中(比如 git), venv.pip 文件中我的 virtualenv 的实际状态。

这是一个示例工作流程:


设置 virtualenv 工作区,带有版本跟踪:

mkdir /tmp/pip_uninstalling
cd /tmp/pip_uninstalling
virtualenv venv
. venv/bin/activate

初始化版本跟踪系统:

git init
echo venv > .gitignore
pip freeze > venv.pip
git add .gitignore venv.pip
git commit -m "Python project with venv"

安装一个包含依赖的包,将其包含在需求文件中:

echo flask > requirements.txt
pip install -r requirements.txt
pip freeze > venv.pip

现在开始构建您的应用,然后提交并启动一个新分支:

vim myapp.py
git commit -am "Simple flask application"
git checkout -b "experiments"

安装一个额外的包:

echo flask-script >> requirements.txt
pip install -r requirements.txt
pip freeze > venv.pip

...玩一下,然后回到早期版本

vim manage.py
git commit -am "Playing with flask-script"
git checkout master

现在卸载无关的包:

pip freeze | grep -v -f venv.pip | xargs pip uninstall -y

我想这个过程可以用 git hooks 自动化,但我们不要跑题。

当然,使用一些包缓存系统是有意义的 或本地存储库,如 pip2pi

【讨论】:

    【解决方案7】:

    这是一个有效的简单解决方案:

    pip uninstall $(pip freeze) -y

    【讨论】:

      【解决方案8】:

      这里搭载 @stephen-j-fuhry 是我使用的 powershell 等价物:

      pip freeze | ? { $_ -notmatch ((gc req.txt) -join "|") }
      

      【讨论】:

        【解决方案9】:

        虽然这不能直接回答问题,但现在requirements.txt 的更好替代方法是使用Pipfile。这个功能类似于 Ruby Gemfile。目前,您需要使用pipenv 工具,但希望最终将其合并到pip 中。这提供了 pipenv clean 命令,它可以满足您的需求。

        (请注意,您可以使用pipenv install -r requirements.txt 导入现有的requirements.txt。在此之后,您应该有一个Pipfile,并且可以删除requirements.txt。)

        【讨论】:

          【解决方案10】:

          现在可以使用:

          pip uninstall -r requirements.txt
          

          【讨论】:

          • 这不会卸载未出现在需求文件中的软件包。它会卸载所有确实出现在文件中的包。
          猜你喜欢
          • 2018-07-27
          • 2018-06-28
          • 1970-01-01
          • 1970-01-01
          • 2018-11-08
          • 1970-01-01
          • 1970-01-01
          • 2016-09-23
          • 2013-01-12
          相关资源
          最近更新 更多