为什么 `pip3 install numpy` 比在 `install_requires` 中设置快得多?

Why is `pip3 install numpy` much faster than setting it in `install_requires`?

以下发生在 Python 3 虚拟环境中。

我刚刚编写了一个需要 numpy 的小包。所以,在setup.py中,我写了install_requires=['numpy']。我 运行 python3 setup.py install,这花了大约两分钟的时间——我得到了通常在 numpy 安装中附带的日志、警告和配置的全屏转储。

然后,我创建了一个新的虚拟环境,这次只写了pip3 install numpy——只用了几秒钟——然后是运行python3 setup.py install,我是几乎立即完成。

两者有什么区别,为什么 pip3 install numpy 快得多?因此,我是否应该包含一个 requirements.txt 以便人们可以 pip-install 要求而不是使用 setuptools?


注意我写pip3 install numpy的时候得到的是:

Collecting numpy
  Using cached numpy-1.12.0-cp36-cp36m-manylinux1_x86_64.whl
Installing collected packages: numpy
Successfully installed numpy-1.12.0

这有没有可能因为 numpy 轮子已经被缓存了所以速度快了很多?

pip install 使用 wheel 包,这些包的设计部分目的是为了加快安装过程。

引入wheel格式的Rationale section of PEP 427指出:

Python needs a package format that is easier to install than sdist. Python's sdist packages are defined by and require the distutils and setuptools build systems, running arbitrary code to build-and-install, and re-compile, code just so it can be installed into a new virtualenv. This system of conflating build-install is slow, hard to maintain, and hinders innovation in both build systems and installers.

Wheel attempts to remedy these problems by providing a simpler interface between the build system and the installer. The wheel binary package format frees installers from having to know about the build system, saves time by amortizing compile time over many installations, and removes the need to install a build system in the target environment.

wheel 安装速度更快,因为它是 Built Distribution format:

Built Distribution

A Distribution format containing files and metadata that only need to be moved to the correct location on the target system, to be installed. Wheel is such a format, whereas distutil’s Source Distribution is not, in that it requires a build step before it can be installed. This format does not imply that python files have to be precompiled (Wheel intentionally does not include compiled python files).

由于 numpy 的源代码分发包含大量 C 代码,因此编译它需要花费大量时间,您在通过裸 setuptools 安装它时观察到这一点。 pip 避免了 C 代码的编译,因为轮子带有二进制代码(已经为您的系统编译)。