解决新的 pip 回溯运行时问题

版本20.3发布的 新的点依赖解析器安装软件包花费的时间过长。 在我们昨天的 CI 管道中,一个 docker 构建过去需要大约10分钟的时间来完成像下面这样的 pip 安装消息(几乎对于任何依赖安装的每个库都有一个类似的日志输出) :

INFO: pip is looking at multiple versions of setuptools to determine which version is compatible with other requirements. This could take a while.
Downloading setuptools-50.0.0-py3-none-any.whl (783 kB)
Downloading setuptools-49.6.0-py3-none-any.whl (803 kB)
Downloading setuptools-49.5.0-py3-none-any.whl (803 kB)
Downloading setuptools-49.4.0-py3-none-any.whl (803 kB)
Downloading setuptools-49.3.2-py3-none-any.whl (790 kB)
INFO: This is taking longer than usual. You might need to provide the dependency resolver with stricter constraints to reduce runtime. If you want to abort this run, you can press Ctrl + C to do so. To improve how pip performs, tell us what happened here: https://pip.pypa.io/surveys/backtracking
Downloading setuptools-49.3.1-py3-none-any.whl (790 kB)
Downloading setuptools-49.3.0-py3-none-any.whl (790 kB)
Downloading setuptools-49.2.1-py3-none-any.whl (789 kB)
Downloading setuptools-49.2.0-py3-none-any.whl (789 kB)
Downloading setuptools-49.1.3-py3-none-any.whl (789 kB)
Downloading setuptools-49.1.2-py3-none-any.whl (789 kB)
Downloading setuptools-49.1.1-py3-none-any.whl (789 kB)
Downloading setuptools-49.1.0-py3-none-any.whl (789 kB)
Downloading setuptools-49.0.1-py3-none-any.whl (789 kB)
Downloading setuptools-49.0.0-py3-none-any.whl (789 kB)
Downloading setuptools-48.0.0-py3-none-any.whl (786 kB)
Downloading setuptools-47.3.2-py3-none-any.whl (582 kB)
Downloading setuptools-47.3.1-py3-none-any.whl (582 kB)
Downloading setuptools-47.3.0-py3-none-any.whl (583 kB)
Downloading setuptools-47.2.0-py3-none-any.whl (583 kB)
Downloading setuptools-47.1.1-py3-none-any.whl (583 kB)
Downloading setuptools-47.1.0-py3-none-any.whl (583 kB)
Downloading setuptools-47.0.0-py3-none-any.whl (583 kB)
Downloading setuptools-46.4.0-py3-none-any.whl (583 kB)
Downloading setuptools-46.3.1-py3-none-any.whl (582 kB)
Downloading setuptools-46.3.0-py3-none-any.whl (582 kB)
Downloading setuptools-46.2.0-py3-none-any.whl (582 kB)
Downloading setuptools-46.1.3-py3-none-any.whl (582 kB)
Downloading setuptools-46.1.2-py3-none-any.whl (582 kB)
Downloading setuptools-46.1.1-py3-none-any.whl (582 kB)
Downloading setuptools-46.1.0-py3-none-any.whl (582 kB)
Downloading setuptools-46.0.0-py3-none-any.whl (582 kB)
Downloading setuptools-45.3.0-py3-none-any.whl (585 kB)
Downloading setuptools-45.2.0-py3-none-any.whl (584 kB)
Downloading setuptools-45.1.0-py3-none-any.whl (583 kB)
Downloading setuptools-45.0.0-py2.py3-none-any.whl (583 kB)
Downloading setuptools-44.1.1-py2.py3-none-any.whl (583 kB)
Downloading setuptools-44.1.0-py2.py3-none-any.whl (583 kB)
Downloading setuptools-44.0.0-py2.py3-none-any.whl (583 kB)
Downloading setuptools-43.0.0-py2.py3-none-any.whl (583 kB)
Downloading setuptools-42.0.2-py2.py3-none-any.whl (583 kB)
Downloading setuptools-42.0.1-py2.py3-none-any.whl (582 kB)
Downloading setuptools-42.0.0-py2.py3-none-any.whl (582 kB)
Downloading setuptools-41.6.0-py2.py3-none-any.whl (582 kB)
Downloading setuptools-41.5.1-py2.py3-none-any.whl (581 kB)
Downloading setuptools-41.5.0-py2.py3-none-any.whl (581 kB)
Downloading setuptools-41.4.0-py2.py3-none-any.whl (580 kB)
Downloading setuptools-41.3.0-py2.py3-none-any.whl (580 kB)
Downloading setuptools-41.2.0-py2.py3-none-any.whl (576 kB)
Downloading setuptools-41.1.0-py2.py3-none-any.whl (576 kB)
Downloading setuptools-41.0.1-py2.py3-none-any.whl (575 kB)
Downloading setuptools-41.0.0-py2.py3-none-any.whl (575 kB)
Downloading setuptools-40.9.0-py2.py3-none-any.whl (575 kB)
Downloading setuptools-40.8.0-py2.py3-none-any.whl (575 kB)
Downloading setuptools-40.7.3-py2.py3-none-any.whl (574 kB)
Downloading setuptools-40.7.2-py2.py3-none-any.whl (574 kB)
Downloading setuptools-40.7.1-py2.py3-none-any.whl (574 kB)
Downloading setuptools-40.7.0-py2.py3-none-any.whl (573 kB)
Downloading setuptools-40.6.3-py2.py3-none-any.whl (573 kB)
Downloading setuptools-40.6.2-py2.py3-none-any.whl (573 kB)
Downloading setuptools-40.6.1-py2.py3-none-any.whl (573 kB)
Downloading setuptools-40.6.0-py2.py3-none-any.whl (573 kB)
Downloading setuptools-40.5.0-py2.py3-none-any.whl (569 kB)
Downloading setuptools-40.4.3-py2.py3-none-any.whl (569 kB)
Downloading setuptools-40.4.2-py2.py3-none-any.whl (569 kB)
Downloading setuptools-40.4.1-py2.py3-none-any.whl (569 kB)
Downloading setuptools-40.4.0-py2.py3-none-any.whl (568 kB)
Downloading setuptools-40.3.0-py2.py3-none-any.whl (568 kB)

我很困惑,我们是否正确地使用新的点解析器,特别是因为

- Substantial improvements in new resolver for performance, output and error messages, avoiding infinite loops, and support for constraints files.

所看到的行为在发布说明中被描述为 回溯。 它指定我可以使用一个约束文件(看起来类似于 requments.txt)来修复依赖项的版本,从而减少运行时使用 pip install -c constraints.txt setup.py.

生成这个约束文件的最佳方法是什么?目前,我能想到的最好的方法是在一个新的虚拟环境中本地运行 pip install setup.py,然后使用 pip freeze > constraints.txt。然而,这对于本地安装来说仍然需要很多时间(现在已经卡住了大约10分钟)。 笔记上确实提到了 This means the “work” is done once during development process, and so will save users this work during deployment.

使用旧的依赖解析器,我能够在不到一分钟的时间内在本地安装这个包。

这里推荐的流程是什么?

编辑: 我刚刚发现一些依赖项直接指向内部的 gitlab 服务器。如果我直接从我们的内部软件包注册中心安装,它会在几分钟内再次工作。

71722 次浏览

因此,他们正在改变解析器,这似乎是一个错误。真正起作用的是使用旧的解析器,通过使用标志

--use-deprecated=legacy-resolver

这将工作到 pip 21.0显然。

来源 Https://github.com/pypa/pip/issues/9215

我已经钉住了所有的依赖项。你将不得不钉他们以后或现在所以更好地做到这一点。我在 pip 20.3.1频道

如果我们不固定任何依赖项,新的依赖项解析器算法将根据从最新版本到初始版本标记的每个依赖项检查每个可用版本。

最新修订(2022-02)

pip中似乎有几天前的重大更新(版本 22.0释放通知书 + 相关问题)。

我还没有测试它的更多细节,但它真的似乎对我来说,他们优化安装顺序计算在复杂的情况下,这样的方式,它解决了许多问题,我们都遇到了前面。但我需要更多时间来检查。

无论如何,这个答案的其余部分仍然是有效的,适合于特定项目的智能需求固定是一个很好的实践。


由于我遇到了类似的问题,我同意这是相当恼人的。回溯可能是一个有用的功能,但是您不想等上几个小时才能完成不确定的成功。

我找到了几个可能有帮助的选择:

  • 使用旧的解析器(--use-deprecated=legacy-resolver)提出的答案由 @ Daniel Davee,但这更像是一个临时解决方案,而不是一个适当的。
  • 使用 --no-deps选项跳过解析依赖项。我一般不推荐这样做,但是在某些情况下,您可以有一个工作包版本集,尽管存在一些冲突。
  • 降低版本的数量 pip 将尝试回溯和更严格的包依赖。这意味着我可以尝试使用 numpy >= 1.18.0或者更严格地使用 numpy == 1.18.0,而不是将例如 numpy放在我的 requments.txt 中。严格也许会有很大帮助。

查阅以下资料来源:

我仍然没有一个合适的答案,这总是有帮助的,但是,Requments.txt 的最佳实践似乎是“别针”软件包版本。我找到了 工具,它甚至可以帮助您管理 strains.txt (但是我还处于实验阶段,所以我不能告诉您更多)。

更新(2021-04)

这个问题的作者似乎能够解决这个问题(一些自定义 gitlab 服务器的东西) ,但我想扩展这个答案,因为它可能对其他人有用。

在阅读和尝试之后,我最终将所有的软件包版本都固定在一个特定的版本上。这真的应该是正确的方法。尽管没有它一切都可以正常工作,但是如果你不固定你的依赖关系,你的软件包管理器会悄悄地安装一个新版本(当它发布的时候) ,这个版本可能会有 bug 或者不兼容(我去年使用 dask的时候就遇到过这种情况)。

有几个工具可以帮助你,我推荐其中一个方法:

pipreqs最简单的

  • Pipreqs 是一个库,它基于任何项目的导入生成 pip demand ments.txt 文件
  • 您可以从 pip install pipreqs开始,并在项目根目录中仅运行 pipreqs(如果您的需求已经存在,最终可以使用 --force标志)
  • 它将很容易地创建 requirements.txt钉住了版本的基础上在您的项目中的导入和版本从您的环境
  • 然后您可以在任何时候创建新的环境基于这个 requirements.txt

这是一个非常简单的工具(您甚至不需要编写需求.txt)。它不允许你创建复杂的东西(对于大型项目来说可能不是一个好的选择) ,上周我发现了一个奇怪的行为(参见 这个) ,但总的来说我对这个工具很满意,因为它通常工作得很完美。

使用 pip-tools

还有其他一些常用的工具,如 工具Pipenv诗歌。你可以阅读更多的 使用 pipenv、诗歌或 pip-tools 构建更快的 Docker2018年的 Python 应用程序依赖管理(旧的,但似乎仍然对我有效)。在我看来,最好的选择(尽管这取决于您的项目/用例)仍然是 pip-tools

您可以(这是一个选项,请参阅 医生中的更多内容) :

  • Create requirements.in(与 requirements.txt相同的格式,是否针对某些包依赖性取决于您)
  • 然后可以通过 pip install pip-tools使用它并运行 pip-compile requirements.in
  • 这将生成新的 requirements.txt文件,其中所有版本都是 钉住了,很明显,什么是原点
  • (可选)您可以运行它与 --generate-hashes选项
  • 然后您可以(与 pipreqs一样)在任何时候创建基于此 requirements.txt的新环境
  • pip-tools为您提供 --upgrade选项升级最终要求
  • 支持分层需求(例如,拥有开发人员和产品版本)
  • 提前承诺集成
  • 提供 pip-sync工具来更新您的环境

还有一些东西你可以用它来做,我真的很喜欢与 pre-commit的集成。这允许您使用与以前相同的要求(只是带有 .in后缀) ,并添加自动更新 requirements.txt的预提交钩子(因此您将永远不会体验到与生成的 requirements.txt不同的本地环境,这种情况在手动运行时很容易发生)。

即使我的所有包都是版本修复的,问题仍然存在。我只是把它们更新到最新版本。当然,这带来了额外的努力,保证没有休息,但它似乎为我解决了问题。

对我来说,它从未结束。原因是将 djangorestframework更新为与 django不兼容的版本。我想让它安装 djangorestframework-3.12.4,它依赖于 django >= 2.2,并且在 requirements.txt中也有 django==2.0.2

将 pip 降级到20.x 版本 这是您在 pip 版本21.x 中将面临的问题

有类似的问题,并希望报告的解决方案,为我工作。 我不得不更新 pip 版本

pip install --upgrade pip

事实上,我正在构建一个码头的图像,所以我已经添加了行

RUN pip install --upgrade pip

就在安装需求之前。在写这个答案的时候,安装的 pip 版本是 22.0.3。这样做解决了问题。

我也有同样的问题,所提供的解决方案对我不起作用,即使我固定了所有的依赖项。

因此,我查看了导致 PIP 在控制台输出中回溯的第一个包(包 之前的第一个警告: “ INFO: pip 正在查看 _ _ _ 的多个版本,以确定哪个版本与其他需求兼容。这可能要花点时间。”) ,并将其从 requments.txt 中删除。这为我解决了问题。

在我的例子中,我们使用了一个虚拟环境,它有助于使用 python 3.10.x 而不是3.8.3。

python3.10 -m venv venv
source venv/bin/activate
pip install .

Pip 已经升级到了22.3.1。