为什么你需要升级 pip ?

共 7618字,需浏览 16分钟

 ·

2021-03-04 00:07

更新软件版本可以修复bug,增加新功能和提升性能。例如,NumPy 1.20 添加了类型注释,并在可能的情况下通过使用SIMD来提高性能。如果您要安装NumPy,则可能要安装最新版本。
相反,如果您使用的是旧版本的pip,则安装最新版本的Python软件包可能会失败,或者以较慢,更复杂的方式进行安装。
为什么?这是关于glibc版本控制以及pip如何安装软件包的一系列问题。
让我们看看问题到底是什么,如何解决,最后是什么原因造成的。
旧版本pip的问题
让我们从Ubuntu 18.04 Docker镜像开始着手。该版本的Ubuntu在2018年4月发布,安装有Python 3.6和pip 9 版本。
[itamarst@blake dev]$ docker run -it ubuntu:18.04
root@1a43d55f0524:/# apt-get update
...
root@1a43d55f0524:/# apt-get install --no-install-recommends python3 python3-pip
...
root@1a43d55f0524:/# pip3 --version
pip 9.0.1 from /usr/lib/python3/dist-packages (python 3.6)
目前为止,事情进展顺利。
失败原因#1:从源代码编译
接下来,让我们安装加密程序包,它是PyPI上下载次数最多的Python程序包之一,每月有数百万次下载(通常是间接依赖)。
root@1a43d55f0524:/# pip3 install cryptography
Collecting cryptography
  Downloading https://files.pythonhosted.org/packages/fa/2d/2154d8cb773064570f48ec0b60258a4522490fcb115a6c7c9423482ca993/cryptography-3.4.6.tar.gz (546kB)
    100% |################################| 552kB 1.4MB/s 
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    ModuleNotFoundError: No module named 'setuptools'
    
    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-6jesygn0/cryptography/
程序进展不是很顺利。
这个错误意味着pip要我们编译软件包;如果我们安装了setuptools,编译器和Python开发工具链,这将起作用,但非常慢。
当然,这不只是一个packagePyArrow也会发生相同的问题,例如:
root@1a43d55f0524:/# pip3 install pyarrow
Collecting pyarrow
  Downloading https://files.pythonhosted.org/packages/62/d3/a482d8a4039bf931ed6388308f0cc0541d0cab46f0bbff7c897a74f1c576/pyarrow-3.0.0.tar.gz (682kB)
    100% |################################| 686kB 1.1MB/s 
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    ModuleNotFoundError: No module named 'setuptools'
    
    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-heq6zwd7/pyarrow/
为什么pip试图从头开始编译这些软件包?为什么我们没有获得二进制的、预编译的软件包?
在考虑第二种故障模式之后,我们将稍等一会儿找到答案。
失败原因#2:旧版本
接下来,安装Fil,Python内存分析器https://pythonspeed.com/products/filmemoryprofiler/
root@1a43d55f0524:/# pip3 install filprofiler
Collecting filprofiler
  Downloading https://files.pythonhosted.org/packages/e3/a2/843e7b5f1aba27effb0146c7e564e2592bfc9344a8c8ef0d55245bd47508/filprofiler-0.7.2-cp36-cp36m-manylinux1_x86_64.whl (565kB)
    100% |################################| 573kB 1.8MB/s 
Installing collected packages: filprofiler
Successfully installed filprofiler-0.7.2
安装成功!除了访问FilPyPI页面(https://pypi.org/project/filprofiler/)外,您都会看到``0.7.2`的版本很旧。在撰写本文时,Fil的最新版本是0.14.1。
为什么要安装旧版本?
pipmanylinux轮子
NumPyCryptography的许多软件包都要求在C / C ++ / Cython / Rust / etc中编译一些代码。为了节省您从头开始编译所有内容的需要,维护人员可以将代码的编译版本(“ wheels”)上载到Python Package Index。如果pip碰到适用于您的特定版本的Python和操作系统版本的轮子,它将下载它而不是源代码。
对于Linux,有多种轮子变体:manylinux1manylinux2010manylinux2014。您可以在下载的轮子的文件名中看到正在使用哪个变体。
问题是:旧版本的pip不支持manylinux2010,当然也不支持manylinux2014。Ubuntu 18.04中的pip太旧了,因此它只了解manylinux1。这解释了我们看到的两个问题:
1、如果您查看PyPI上PyArrow 3.0.0的可用文件列表(https://pypi.org/project/pyarrow/3.0.0/#files),您会看到只有很多linux2010linux2014的轮子。因此,pip会回退到需要编译的源代码包。
2、如果检查Fil的PyPI文件(https://pypi.org/project/filprofiler/0.14.1/#files),则会看到有manylinux2010轮子,而根本没有源程序包;因为从源代码构建有点棘手,所以我只分发编译后的程序包。这意味着pip会继续使用该软件包的较早版本,直到找到具有manylinux1轮子的软件包为止。
解决方案:升级pip
为了获得最新最好的软件包,而无需编译,您需要升级到最新版本的pip。如何执行取决于您的安装环境。
通常,您可以执行pip install --upgrade pip来每天进行一次升级。
但是,在某些环境中可能会出现问题。例如,如果您看一下我们如何在Ubuntu 18.04中设置Python,那么我们是通过系统软件包安装pip的。
问题在于,覆盖系统软件包中的随机文件是一个坏主意。除非您在环境中运行,否则在必要时将从头开始重建(例如Docker映像),那么永远不要以root或sudo的身份运行pip install来修改系统软件包。
相反,在Ubuntu 18.04上,您可以通过下载获得pip:
$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
$ python3 get-pip.py
或者您可以创建一个virtualenv虚拟环境,然后通过执行pip install --upgrade pip升级其pip:
root@1a43d55f0524:/# python3 -m venv myvenv
root@1a43d55f0524:/# . myvenv/bin/activate
(myvenv) root@1a43d55f0524:/# pip --version
pip 9.0.1 from /myvenv/lib/python3.6/site-packages (python 3.6)
(myvenv) root@1a43d55f0524:/# pip install --upgrade pip
Collecting pip
  Using cached https://files.pythonhosted.org/packages/fe/ef/60d7ba03b5c442309ef42e7d69959f73aacccd0d86008362a681c4698e83/pip-21.0.1-py3-none-any.whl
Installing collected packages: pip
  Found existing installation: pip 9.0.1
    Uninstalling pip-9.0.1:
      Successfully uninstalled pip-9.0.1
Successfully installed pip-21.0.1
现在,我们有了一个更新后的pip,我们可以轻松地安装最新版本的cryptographyfilprofiler
(myvenv) root@1a43d55f0524:/# pip install cryptography filprofiler
Collecting cryptography
  Downloading cryptography-3.4.6-cp36-abi3-manylinux2014_x86_64.whl (3.2 MB)
     |################################| 3.2 MB 4.5 MB/s 
...
Installing collected packages: pycparser, threadpoolctl, cffi, filprofiler, cryptography
Successfully installed cffi-1.14.5 cryptography-3.4.6 filprofiler-0.14.1 pycparser-2.20 threadpoolctl-2.1.0
注意,我们下载了包含cryptographymanylinux2014软件包。
为什么会有这么多Linux版本存在?
Linux上已编译的Python扩展链接到标准C语言库,特别的是它们链接到GNU Libc(又名glibc)。您可以使用ldd实用工具查看可执行文件或共享库链接到哪些库:
root@1a43d55f0524:/# cd myenv/lib/python3.6/site-packages
root@1a43d55f0524:/# ldd cryptography/hazmat/bindings/_openssl.abi3.so 
        linux-vdso.so.1 (0x00007ffdbea7b000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fba7b1bf000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fba7adce000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fba7b7b0000)
注意,编译后的Python扩展尤其依赖于/lib/x86_64-linux-gnu/libc.so.6,即glibc
如果您用glibc的较新版本编译代码,它可能不需要在旧版本提供新的API或符号。这意味着你的代码不会在旧的Linux发行版上运行。
有许多对这个问题的不同解决方案。Conda通过针对旧版本的glibc头文件来编译所有的包;基本上在广泛的Linux发行版它有一个自定义编译安装设计工作。
PyPI二进制轮子通过编译旧版本的Linux,以及它的相应旧版本的glibc来解决这个问题。因为它是针对旧版本编译的,它会与任何新版本兼容工作。
  • manylinux1包建在CentOS 5。
  • manylinux2010包建在CentOS 6。
  • manylinux2014软件包都建立在CentOS 7上。
每个新版本都需要对应的新发布的pip。你可以学到更多的PEP-571PEP-599
升级您的pip!
无论您是建立一个开发环境或写你的Dockerfile,请确保升级pip。否则,你就会有一个更难的时间安装软件包。


更多阅读



2020 年最佳流行 Python 库 Top 10


2020 Python中文社区热门文章 Top 10


5分钟快速掌握 Python 定时任务框架

特别推荐





点击下方阅读原文加入社区会员

浏览 30
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报