pip 10和apt:如何避免distutils包的"无法卸载X"错误

ele*_*han 41 python apt distutils pip docker

我正在处理遗留的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
Run Code Online (Sandbox Code Playgroud)

首先,使用安装几个软件包apt,然后使用安装几个软件包pip.pip版本10已经发布,部分版本是这个新限制:

删除了对卸载使用distutils安装的项目的支持.distutils安装的项目不包括指示哪些文件属于该安装的元数据,因此实际卸载它们是不可能的,而不是仅删除表示已安装的元数据,同时保留所有实际文件.

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

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.
Run Code Online (Sandbox Code Playgroud)

现在我知道在这一点上有几种解决方案.

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

--ignore-installed当我尝试pip安装已经安装好的东西时,我也可以使用该选项apt,但是我再次对每个--ignore-installed参数都有同样的问题,揭示了另一个需要忽略的事情.

我可以固定pip一个没有这个限制的旧版本,但我不想被pip永远使用过时的版本卡住.

我一直在试图提出一个很好的解决方案,包括对这个传统Dockerfile的最小改动,并允许我们使用该文件部署的应用程序继续运行.有关如何安全解决此问题的任何建议pip10无法安装较新版本的distutils软件包?谢谢!

更新:

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

ele*_*han 86

这是我最终使用的解决方案,并且我们的应用程序已经在生产中运行,在接下来的一个月内没有任何问题,并且此修复程序到位:

我所要做的就是添加

--ignore-installed

pip install我的dockerfile中引发错误的行.使用我原始问题中的相同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
Run Code Online (Sandbox Code Playgroud)

我能找到的文件--ignore-installed在我看来并不清楚(pip install --help简单地说"忽略已安装的软件包(重新安装)."),我在这里询问了这个标志的潜在危险,但还没有得到令人满意的答案.但是,如果有任何负面影响,我们的生产环境尚未看到它们的影响,我认为风险很低/没有(至少这是我们的经验).我能够确认在我们的情况下,当使用此标志时,未卸载现有安装,但始终使用较新的安装.

更新:

我想通过@ivan_pozdeev 强调这个答案.他提供了一些这个答案不包括的信息,他还概述了我的解决方案的一些潜在副作用.

  • 这使得系统的配置不​​受支持,因此无法维护。即使您这次很幸运,在将来进行任何其他包管理操作后,它也可能会以不可预测的方式破坏事情。请参阅 /sf/ask/3766525801/#53807588 上的注释 (2认同)

小智 6

这就是对我有用的-

pip install --ignore-installed <Your package name>
Run Code Online (Sandbox Code Playgroud)

要么

sudo pip install --ignore-installed <Your package name>
Run Code Online (Sandbox Code Playgroud)

或(在jupyter笔记本中)

import sys
!{sys.executable} -m pip install --ignore-installed <Your package name>
Run Code Online (Sandbox Code Playgroud)