pip 10 和 apt:如何避免 distutils 包的 "Cannot uninstall X" 错误

pip 10 and apt: how to avoid "Cannot uninstall X" errors for distutils packages

我正在处理遗留的 Dockerfile。这是我正在处理的非常简化的版本:

FROM ubuntu:14.04

RUN apt-get -y update && apt-get -y install \
    python-pip \
    python-numpy # ...and many other packages

RUN pip install -U pip

RUN pip install -r /tmp/requirements1.txt # includes e.g., numpy==1.13.0
RUN pip install -r /tmp/requirements2.txt
RUN pip install -r /tmp/requirements3.txt

首先,使用 apt 安装几个包,然后使用 pip 安装几个包。 pip版本10已经发布,part of the release是这个新的限制:

Removed support for uninstalling projects which have been installed using distutils. distutils installed projects do not include metadata indicating what files belong to that install and thus it is impossible to actually uninstall them rather than just remove the metadata saying they've been installed while leaving all of the actual files behind.

这导致我的设置出现以下问题。例如,首先 apt 安装 python-numpy。后来 pip 尝试从 /tmp/requirements1.txt 安装更新版本的 numpy,并尝试卸载旧版本,但由于新的限制,它无法删除此版本:

Installing collected packages: numpy
  Found existing installation: numpy 1.8.2
Cannot uninstall 'numpy'. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall.

现在我知道此时有几种解决方案。

我无法通过 apt 安装 python-numpy。但是,这会导致问题,因为 python-numpy 根据要求安装了几个不同的包,我不知道系统的另一部分是否依赖这些包。实际上,通过 Dockerfile 安装了几个 apt 包,我删除的每个包似乎都显示了另一个 Cannot uninstall X 错误,并删除了许多其他包,我们的应用程序可能或可能不靠。

当我尝试 pip 安装已经通过 apt 安装的东西时,我也可以使用 --ignore-installed 选项,但是我又遇到了每个 --ignore-installed 论点揭示了另一件需要忽略的事情。

我可以将 pip 固定在没有此限制的旧版本上,但我不想永远使用 pip 的过时版本。

我一直在兜圈子试图想出一个好的解决方案,该解决方案涉及对这个遗留 Dockerfile 的最小更改,并允许我们使用该文件部署的应用程序继续像以前一样运行。关于如何安全解决 pip 10 无法安装更新版本的 distutils 软件包的问题,​​有什么建议吗?谢谢!

更新:

我没有意识到 --ignore-installed 可以在没有包的情况下用作参数来忽略所有已安装的包。我正在考虑这对我来说是否是一个不错的选择,并询问了它 here

您可以只手动删除 numpy,但保留由 apt 安装的其他依赖项。然后像以前一样使用pip安装最新版本的numpy。

#Manually remove just numpy installed by distutils
RUN rm /usr/lib/python2.7/dist-packages/numpy-1.8.2.egg-info
RUN rm -r /usr/lib/python2.7/dist-packages/numpy

RUN pip install -U pip
RUN pip install -r /tmp/requirements1.txt

numpy的位置应该是一样的。但是,如果您想确认位置,您可以 运行 容器而不 运行 宁 requirements.txt 文件,并在容器内的 python 控制台中发出以下命令。

>>> import numpy
>>> print numpy.__file__
/usr/lib/python2.7/dist-packages/numpy/__init__.pyc

这是我最终采用的解决方案,并且我们的应用程序已经 运行 投入生产,近一个月没有出现任何问题,并进行了此修复:

我所要做的就是添加

--ignore-installed

到我的 dockerfile 中引发错误的 pip install 行。使用我最初问题中的相同 dockerfile 示例,固定的 dockerfile 看起来像:

FROM ubuntu:14.04

RUN apt-get -y update && apt-get -y install \
    python-pip \
    python-numpy # ...and many other packages

RUN pip install -U pip

RUN pip install -r /tmp/requirements1.txt --ignore-installed # don't try to uninstall existing packages, e.g., numpy
RUN pip install -r /tmp/requirements2.txt
RUN pip install -r /tmp/requirements3.txt

我能找到的关于 --ignore-installed 的文档在我看来并不明确(pip install --help 只是说 "Ignore the installed packages (reinstalling instead)."),我询问了这个标志的潜在危险 here,但至今仍未得到满意的答复。但是,如果有任何负面影响,我们的生产环境还没有看到它们的影响,我认为风险是low/none(至少这是我们的经验)。我能够确认,在我们的例子中,当使用这个标志时,现有的安装没有被卸载,但总是使用较新的安装。

更新:

我想强调@ivan_pozdeev 的 回答。他提供了此答案未包含的一些信息,并且还概述了我的解决方案的一些潜在副作用。

这对我有用--

pip install --ignore-installed <Your package name>

sudo pip install --ignore-installed <Your package name>

或(在 jupyter notebook 内)

import sys
!{sys.executable} -m pip install --ignore-installed <Your package name>

对于windows 写

conda update --all pip install --upgrade <Your package name>

conda update --all pip install <Your package name>

pip install wrapt --upgrade --ignore-installed pip install <Your package name>

来自 ERROR: Cannot uninstall 'wrapt'. during upgrade