Pip vs Conda:深入比较 Python 的两种打包系统
如果您在数据科学或科学计算领域使用 Python,您很快就会发现 Python 有两种不同的打包系统:pip 和 Conda。这就提出了一些问题:
- 它们它们
- 两者之间有什么取舍?
- 哪个?
虽然不可能在每种情况下都回答这个问题,但在本文中,您将了解基本差异,仅限于:
- 仅限 Python;Conda 支持其他语言,但我不会深入讨论。
- Linux,包括在 Docker 上运行,但也提到了 macOS 和 Windows。
- 专注于 Conda-Forge 包存储库;Conda 有多个包存储库或“通道”。
最后,您应该了解 Conda 存在的原因、何时可能需要使用它,以及在选择每一个之间的权衡。
出发点:哪种依赖?
pip 和 Conda 打包的根本区别在于它们放在包中的内容。
- Pip 包是 Python 库,如 NumPy 或
matplotlib
. - Conda 包包括 Python 库(NumPy 或
matplotlib
)、C 库 (libjpeg
) 和可执行文件(如 C 编译器,甚至 Python 解释器本身)。
Pip:仅限 Python 库
例如,假设您要安装带有 NumPy、Pandas 和 gnuplot 渲染工具(与 Python 无关的工具)的 Python 3.9。这是 pip 的requirements.txt
样子:
安装 Python 和 gnuplot超出了 pip的范围。您作为用户必须自己处理。例如,您可以使用 Docker 映像执行此操作:
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y gnuplot python3.9
COPY requirements.txt .
RUN pip install -r requirements.txt
Python 解释器和 gnuplot 都需要来自系统包,在这种情况下是 Ubuntu 的包。
Conda:任何依赖都可以是一个 Conda 包(几乎)
对于 Conda,Python 和 gnuplot 只是更多的 Conda 包,与 NumPy 或 Pandas 没有什么不同。该environment.yml
对应(有点)的requirements.txt
,我们看到上面会包括所有这些软件包:
name: myenv
channels:
- conda-forge
dependencies:
- python=3.9
- numpy
- pandas
- gnuplot
Conda 仅依赖于操作系统的基本功能,如标准 C 库。上面的一切都是 Conda 包,而不是系统包。
如果对应Dockerfile
,我们可以看到差异; 无需安装任何系统包:
FROM continuumio/miniconda3
COPY environment.yml .
RUN conda env create
此基础映像附带预安装的 Conda,但我们不依赖任何现有的 Python 安装,我们将在新环境中安装一个新的。
注意:在讨论的非常具体的主题之外,本文中的 Dockerfile 不是最佳实践的示例,因为增加的复杂性会掩盖本文的要点。
为确保您遵循获得安全、正确、快速 Dockerfile 所需的所有最佳实践,请查看Python on Docker Production Handbook。
为什么 Conda 打包一切
为什么 Conda 决定打包所有东西,包括 Python 解释器?这对你有什么好处?部分是关于便携性和可再现性。
- 跨操作系统的可移植性:无需在 Linux、macOS 和 Windows 上以三种不同的方式安装 Python,您可以在这三种方式上使用相同的方式
environment.yml
。 - 重现性:可以固定几乎整个堆栈,从 Python 解释器向上。
- 配置一致:不需要以两种不同的方式安装系统包和Python包;(几乎)一切都可以放在一个文件中,
environment.yml
.
但它也解决了另一个问题:如何处理需要编译代码的 Python 库。这是一个足够大的主题,它接下来会有一个全新的部分。
超越纯 Python:打包编译的扩展
在 Python 打包的早期,一个包只包含需要安装的源代码。对于纯 Python 包,这工作得很好,现在仍然如此。但是当您需要编译一些 Rust 或 C 或 C++ 或 Fortran 代码作为构建包的一部分时会发生什么?
解决方案#1:自己编译
最初的解决方案是让每个用户在安装时自己编译代码。这可能很慢,浪费资源,配置起来通常很痛苦,而且仍然没有解决很大一部分问题:共享库依赖项。
例如,枕头图像图形库依赖于第三方共享库,如libpng
和libjpeg
。为了自己编译 Pillow,您必须安装所有这些,以及它们的开发头文件。在 Linux 或 macOS 上,您可以安装系统包或 Homebrew 包;对于 Windows,这可能更困难。但是您将不得不为每个操作系统甚至 Linux 发行版编写不同的配置。
解决方案#2:Pip轮
pip 解决这个问题的方法是使用称为“轮子”的包,它可以包含已编译的代码。为了处理像 的共享库依赖项libpng
,任何共享库外部依赖项都被捆绑在轮子内部。
例如,让我们看看 Linux 的 Pillow wheel;轮子只是一个 ZIP 文件,所以我们可以使用标准的 ZIP 工具:
$ zipinfo Pillow.whl
...
Pillow.libs/libpng16-213e245f.so.16.37.0
Pillow.libs/libjpeg-183418da.so.9.4.0
...
PIL/FpxImagePlugin.py
PIL/PalmImagePlugin.py
...
PIL/_imagingcms.cpython-39-x86_64-linux-gnu.so
...
轮子包括 Python 代码、编译的 Python 扩展和第三方共享库,如libpng
和libjpeg
. 这有时会使包变大,因为可能会安装第三方共享库的多个副本,每个轮一个。
解决方案 #3:Conda 包
Conda 包对第三方共享库采用不同的方法。libjpeg
并libpng
打包为额外的 Conda 包:
$ conda install -c conda-forge pillow
...
The following NEW packages will be INSTALLED:
...
jpeg conda-forge/linux-64::jpeg-9d-h36c2ea0_0
...
libpng conda-forge/linux-64::libpng-1.6.37-h21135ba_2
...
pillow conda-forge/linux-64::pillow-7.2.0-py38h9776b28_2
zstd conda-forge/linux-64::zstd-1.5.0-ha95c52a_0
...
那些已安装libjpeg
,libpng
然后可以被其他已安装的软件包所依赖。它们不是特定于轮子的,它们可用于 Conda 环境中的任何包。
Conda 可以做到这一点,因为它不仅仅是 Python 代码的打包系统;它可以轻松地打包共享库或可执行文件。
总结:pip 与 Conda
点子 | 康达 | |
---|---|---|
安装 Python | 不 | 是的,作为包裹 |
第三方共享库 | 车轮内 | 是的,作为包裹 |
可执行文件和工具 | 不 | 是的,作为包裹 |
Python源代码 | 是的,作为包裹 | 是的,作为包裹 |
PyPI 与 Conda-Forge
pip 和 Conda 之间的另一个根本区别不在于工具本身,而在于它们依赖的包存储库以及它们的工作方式。特别是,大多数 Python 程序将依赖于开源库,这些库需要从某个地方下载。对于这些,pip 依赖于PyPI,而 Conda 支持托管在Anaconda上的多个不同“通道” 。
默认的 Conda 频道由创建 Conda 的公司 Anaconda Inc 维护。它的软件包选择往往有限,更新程度较低,在稳定性和 GPU 支持方面具有一些潜在优势。除此之外,我对此知之甚少。
但是还有Conda-Forge社区频道,它打包了更多的软件包,而且往往是最新的,并且大多数时候您可能希望在那里获得 Conda 软件包。如果您需要默认频道的 GPU 包,您可以混合来自默认频道和 Conda-Forge 的包。
让我们将 PyPI 与 Conda-Forge 进行比较。
PyPI
PyPI 上的包通常由 Python 包的作者上传。例如,我是Fil memory profiler的作者,我还创建了PyPI 包。
每个包维护者都可能以自己独特的方式编译或构建他们的包,维护自己的构建基础设施,选择自己的编译选项,等等。
例如,NumPy 可以依赖多个不同的 BLAS 库进行快速线性代数运算。维护者选择使用 OpenBLAS 构建他们的 PyPI 包;如果你想要另一个选择,比如英特尔的(也许?)更快的 MKL,除非你愿意自己编译代码,否则你就不走运了。
康达福吉
Conda-Forge 是一个社区项目,其中包维护者可以不同于包的原始作者。例如,即使我不是该库的维护者,我也已提交对typeguard
Conda-Forge 配方的访问权限typeguard
。
Conda-Forge 拥有集中的构建系统,可以重新编译库、更新配方存储库,并且通常大规模自动化所有内容,而不是由每个包维护者以不同的方式完成自定义构建。例如,当新版本的 Python 3 出来时,会发生集中更新,所有单独的包维护者都会获得 PR,添加新的包;在 PyPI 上,这取决于个人维护者来解决。
由于打包基础设施是集中式的,Conda-Forge 能够让您选择要使用的 BLAS,它将用于 NumPy 和 SciPy 以及您使用的依赖于 BLAS 的任何其他包。
在 Conda 中处理 PyPI-only 包
虽然 Conda-Forge 有很多包,但并不是所有的包;许多 Python 包只能在 PyPI 上找到。您可以通过多种方式处理缺少这些软件包的问题。
在 Conda 环境中安装 pip 包
Conda 环境是 virtualenvs 的包装器;因此,您可以给pip install
自己打电话。如果你使用 anenvironment.yml
来安装你的 Conda 包,你还可以添加 pip 包:
name: myenv
channels:
- conda-forge
dependencies:
- python=3.9
- numpy
- pandas
- gnuplot
- pip:
# Package that is only on PyPI
- sandu
自己为 Conda-Forge 打包
因为 Conda-Forge 不需要代码的维护者进行打包,所以任何人都可以自愿向 Conda-Forge 添加一个包。那包括你!
对于许多 Python 包来说,这是一个非常简单的过程,而且非常自动化,因此处理新版本通常就像批准自动创建的 PR 一样简单。
总结:PyPI 与 Conda-Forge
PyPI | 康达福吉 | |
---|---|---|
谁创建包? | 代码作者 | 任何人 |
建设基础设施 | 由作者维护 | 集中 |
开源 Python 库 | 基本上所有 | 许多 |
其他开源工具 | 没有任何 | 许多 |
Windows/Linux/macOS 包 | 通常,但由维护者决定 | 几乎总是 |
以下是您可能希望与任一工具一起使用的一些附加工具的快速摘要:
点 | 康达 | |
---|---|---|
可复制的构建 | pip-tools、pipenv、诗歌 | 锁 |
虚拟环境 | python -m venv , virtualenv |
内置 |
安全扫描 | 大多数安全扫描仪 | 杰克 |
备择方案 | 诗歌,pipenv | 曼巴; 速度更快,强烈推荐 |
重申:如果您确实使用 Conda,我强烈建议您使用 Mamba 作为替代品。它支持相同的命令行选项并且速度更快。
你应该使用哪个?
那么你应该使用哪个,pip 还是 Conda?对于一般的 Python 计算,pip 和 PyPI 通常都可以,周围的工具往往会更好。
然而,对于数据科学或科学计算,Conda 打包第三方库的能力,以及 Conda-Forge 提供的集中式基础设施,意味着复杂包的设置通常会更容易。最后,哪种最适合您将取决于您的情况和要求;很可能两者都会好的。
原创文章,作者:flypython,如若转载,请注明出处:http://flypython.com/advanced-python/542.html