学习Python的人一定知道pip install xxx
的作用,但是很少有人会去想背后的东西——pip安装的到底是什么?什么是.whl包?如果哪天我自己想写一个python包,应该怎么做?
我们先来看两个pip安装包的过程。第一个是再熟悉不过的NumPy包:
$ pip install numpy
Collecting numpy
Downloading numpy-1.19.4-cp36-cp36m-manylinux2010_x86_64.whl (14.5 MB)
|████████████████████████████████| 14.5 MB 15.1 MB/s
Installing collected packages: numpy
Successfully installed numpy-1.19.4
一个是uWSGI包(用来做什么的不用管)
$ pip install uwsgi
Collecting uwsgi
Downloading uWSGI-2.0.19.1.tar.gz (803 kB)
|████████████████████████████████| 803 kB 274 kB/s
Building wheels for collected packages: uwsgi
Building wheel for uwsgi (setup.py) ... done
Created wheel for uwsgi: filename=uWSGI-2.0.19.1-cp36-cp36m-linux_x86_64.whl size=597269 sha256=f2289db3db6d625f136f794be0319da477ad740eb28cd063971f8d335327c09c
Stored in directory: /private/.cache/pip/wheels/3a/7a/c1/492f02e0cde1e39f8b75c79dc5ef3b7e2c93b02e3a7eaabe0c
Successfully built uwsgi
Installing collected packages: uwsgi
Successfully installed uwsgi-2.0.19.1
细看会发现:
了解了这些区别之后,我们再来铺垫一点发行版的内容。
发行包,说得直白一点就是端用户(比如一个刚开始学Python的小白)下载的东西。一个发行包包含了模组、资源文件等等。用户们下载好发行包就能直接安装使用了。
源发行版,顾名思义就是“发行的是源码”,包含了元数据和源码文件(Python, C++等),必须要经过编译才能使用起来。编译的过程是在用户的机子上进行的。通常用python setup.py sdist
来产生源发行版。
同样地,如果源码被编译好了,那就成了一个已编译的发行版了。我们要谈到的wheel就是已编译发行版的一种格式。有的地方提到二进制发行版(binary distribution)也基本默认是wheel包。(下文如果提到wheel或二进制发行版就默认是已编译发行版了)
所以,结合上面的例子,我们大概可以猜出来NumPy和uWSGI安装上的区别了:NumPy下载的是已编译的发行版,而uWSGI下载的是源发行版,在本地编译完了之后才执行安装。
所以为什么有的包直接提供了wheel,有些包要提供源码呢?
从用户的角度看,wheel包显然就是方便的代名词。能用wheel的时候我们尽量就不要去用别的安装方式了,免得给自己找麻烦。
为了体现使用whl包到底比源码包快多少,我们可以尝试下面两种不同的过程来安装NumPy:
# 使用源码包安装,即便有PyPi上有whl包可以使用
# --no-cache-dir:不适用本地缓存,始终从PyPi上面下载
# --force-reinstall:强制重新安装,即便这个包在系统里已经最新
# --no-binary=:all: :不允许使用二进制包,:all:表示对所有相关的依赖包也采用同样的选择
time python -m pip install --no-cache-dir --force-reinstall --no-binary=:all: numpy
# 使用whl包安装
# --only-binary=numpy:指定针对numpy使用二进制包(即已编译好的发行版)
time python -m pip install -no-cache-dir --force-reinstall --only-binary=numpy numpy
在采用第一种方式的时候,你还很有可能遇到报错,说有一些依赖的头文件没找到,这也从侧面凸显了whl的好处:不用怎么担心依赖关系。
从开发者的角度来看,提供whl或是源发行包则取决于对项目复杂性、相互依赖关系以及其他因素的综合考量。如果要提供whl包,那就要针对不同的平台都要准备,对兼容性要有比较全面的考虑。
wheel包本质上是一个zip文件。是已编译发行版的一种格式。需要注意的是,尽管它是已经编译好的,包里面一般不包含.pyc
或是Python字节码。一个wheel包的文件名由以下这些部分组成:
{dist}-{version}(-{build})?-{python}-{abi}-{platform}.whl
举个例子:
tensorflow-2.3.1-cp36-cp36m-macosx_10_9_x86_64.whl
再举个例子:
requests-2.7.0-py2.py3-none-any.whl (470.6 kB)
还有个例子:
tensorflow-2.3.1-cp35-cp35m-manylinux2010_x86_64.whl
manylinux1
(PEP513),manylinux2010
(PEP571)和manylinux2014
(PEP599)。以上就是作为一个普通用户需要了解的关于wheel包的知识了。下一篇(如果没有放鸽子的话)打算来谈一谈作为开发者如何去创建、发布你的wheel包。