使用pip 10与apt时,如何规避distutils包的“无法卸载X”错误
解决Docker中pip无法卸载distutils包的"Cannot uninstall X"错误
这个问题我碰到太多次了——你先通过apt装了系统级的Python包(比如这里的python-numpy),之后又想用pip安装同一包的特定版本,而pip默认不允许卸载由distutils管理的系统包,自然就弹出"Cannot uninstall X"的错误了。下面给你几个实用的解决思路:
方案1:移除apt安装的冲突包
既然系统包和pip包本质上是同一依赖的不同版本,最直接的办法就是把apt装的那个版本删掉,交给pip统一管理:
FROM ubuntu:14.04 RUN apt-get -y update && apt-get -y install \ python-pip # 去掉python-numpy,让requirements里的numpy版本由pip安装 RUN pip install -U pip RUN pip install -r /tmp/requirements1.txt # 这里包含numpy==1.13.0 RUN pip install -r /tmp/requirements2.txt RUN pip install -r /tmp/requirements3.txt
如果有其他apt依赖必须用到系统级numpy,你可以先安装它完成必要操作,之后再卸载:
RUN apt-get -y install python-numpy && \ # 执行依赖系统numpy的操作(比如某些系统工具初始化) apt-get -y purge --auto-remove python-numpy
方案2:用pip的--ignore-installed参数强制覆盖
要是你不想改动apt安装步骤,或者必须保留系统包,可以在pip安装时加上--ignore-installed参数,强制让pip忽略已存在的系统版本,直接安装需求文件里指定的版本:
RUN pip install -U pip # 只针对numpy忽略已安装版本,避免影响其他系统依赖包 RUN pip install --ignore-installed numpy -r /tmp/requirements1.txt
注意:如果直接给整个需求文件加这个参数,会忽略所有已安装的包,容易破坏系统依赖,所以最好单独指定冲突的包再追加需求文件。
方案3:用虚拟环境彻底隔离依赖
在Docker里用Python虚拟环境是更稳妥的长期方案,能完全隔离系统Python环境和你的应用依赖:
FROM ubuntu:14.04 RUN apt-get -y update && apt-get -y install \ python-pip \ python-virtualenv # 创建虚拟环境 RUN virtualenv /app/venv # 用虚拟环境里的pip安装所有依赖 RUN /app/venv/bin/pip install -U pip RUN /app/venv/bin/pip install -r /tmp/requirements1.txt RUN /app/venv/bin/pip install -r /tmp/requirements2.txt RUN /app/venv/bin/pip install -r /tmp/requirements3.txt # 运行应用时也要用虚拟环境里的Python CMD ["/app/venv/bin/python", "your_app.py"]
这样系统级的包和应用依赖完全不干涉,从根源上杜绝这类冲突问题。
小技巧:优化Docker镜像分层
最后提个小建议,你可以把多个pip install命令合并成一个,减少镜像层数,同时更好地利用Docker缓存:
RUN pip install -U pip && \ pip install --ignore-installed numpy \ -r /tmp/requirements1.txt \ -r /tmp/requirements2.txt \ -r /tmp/requirements3.txt
内容的提问来源于stack exchange,提问作者elethan
相关产品推荐
相关产品推荐

