每个数据科学家都应该了解 Python 依赖

简介: 什么是依赖管理?依赖管理是管理项目所依赖的所有外部部分的行为。 当它起作用时,你甚至不知道它的存在,但当它失败时,它变得非常痛苦,几乎不可能被忽视。

什么是依赖管理?

依赖管理是管理项目所依赖的所有外部部分的行为。 当它起作用时,你甚至不知道它的存在,但当它失败时,它变得非常痛苦,几乎不可能被忽视。

每个项目都是建立在别人的汗水和泪水之上的。 那些工程师醒来、煮咖啡并通过编写引导加载程序(从头启动计算机的程序)开始一个新项目的日子已成为历史。 我们下面有大量的软件和库。 我们只是在上面撒上一层薄薄的糖。

我的电脑的软件堆栈与你的不同。 不仅堆栈不同,而且它们永远在变化。 任何事情的运作方式都令人惊讶,但确实如此。这一切都要归功于依赖管理和许多聪明的人对这些层进行抽象,这样我们就可以调用我们最喜欢的 pandas 函数并获得可预测的结果。


Python 依赖管理基础

让我们澄清一件事。 简单地安装和升级 Python 包不是依赖管理。 依赖管理是记录您的项目所需的环境,并使其他人可以轻松且确定地复制它。

您可以在一张纸上写下安装说明。 您可以将它们写在源代码注释中。 您甚至可以将安装命令直接硬编码到程序中。

推荐的方法是以标准化、可重现、广泛接受的格式将依赖信息与代码解耦。 这使版本固定和简单的确定性安装成为可能。 通常,有很多选择,但我们将在本文中描述 pip 和 requirements.txt 文件的经典组合。

但是在我们去之前,让我们先介绍一下Python依赖的原子单元:包。



什么是包?

“包”是 Python 中定义明确的术语。 库、框架、工具包等术语不是。 在本文的其余部分,我们将使用术语“包”,即使是一些称为库、框架或工具包的东西。

模块是在单个 Python 文件中定义的所有内容(类、函数等)。

包是模块的集合。

Pandas 是一个包,Matplotlib 是一个包,print()函数不是一个包。 包的目的是成为一个易于分发、可重用和版本化的模块集合,这些模块对其他包具有明确的依赖关系。

你可能每天都在使用包,通过 Python import语句在代码中引用它们。



安装包的艺术

虽然您可以通过简单地将包手动下载到项目中来安装包,但最常见的安装包的方法是通过 PyPi(Python 包索引)使用著名的 pip install 命令。

注意:切勿使用 sudo pip install。 这就像运行病毒一样。 结果是不可预测的,会导致你在未来的面临重大的痛苦。

也不要全局安装 Python 包。 强烈建议始终使用虚拟环境。



什么是虚拟环境?

Python 虚拟环境是一个安全的气泡。您应该在本地计算机上的所有项目周围创建一个保护气泡。如果你不这样做,项目就会互相损害。

如果您在气泡之外调用pip install pandas,它将被全局安装。这是不好的。世界在前进,包也在前进。一个项目需要 2019 年的 Matplotlib,另一个项目需要 2021 年的版本。单个全局安装不能同时服务于两个项目。所以保护气泡是必要的。让我们看看如何使用它们。

转到您的项目根目录并创建一个虚拟环境:

python3 -m venv mybubble
复制代码


现在我们有一个气泡,但我们还没有进入气泡中。现在,我们进去吧!

source mybubble/bin/activate
复制代码


现在我们处于气泡中。您的终端应在括号中显示虚拟环境名称,如下所示:

(mybubble) johndoe@hello:~/myproject$
复制代码


现在我们处于气泡中,安装包是安全的。从现在开始,任何 pip install 命令都只会在虚拟环境内部产生影响。您运行的任何代码都只会使用气泡内的包。

如果您列出已安装的软件包,您应该会看到一个非常短的当前安装的默认软件包列表(如: pip 本身)。

pip list
Package       Version
------------- -------
pip           20.0.2 
pkg-resources 0.0.0  
setuptools    44.0.0
复制代码


此列表不再针对您机器中的所有 Python 包,而是针对您虚拟环境中的所有 Python 包。此外,请注意,气泡内使用的 Python 版本是您用于创建气泡的 Python 版本。

要离开气泡,只需调用 deactivate 命令。

始终为您的所有本地项目创建虚拟环境并在这些气泡中运行您的代码。项目之间的包版本冲突带来的痛苦是让人们辞职的那种痛苦。不要成为那些人中的一员。



什么是版本固定?

想象一下,您有一个依赖于 Pandas 包的项目,并且您想将其传达给世界其他地方(以及您未来的自己)。应该很容易,对吧?

首先,如果仅仅说:“你需要 Pandas”是有风险的。

风险较小的选项是“您需要 Pandas 1.2.1 版本”,但即使这样也总是不够的。

假设您正确地将 Pandas 版本固定到 1.2.1。 Pandas 本身对 numpy 有依赖关系,但不幸的是,它并没有将依赖关系固定到确切的 numpy 版本。 Pandas 本身只是说“你需要 numpy”,并没有固定到确切的版本。

起初,一切都很好,但六个月后,一个新的 numpy 版本 1.19.6 发布了,其中包含一个显示错误。

现在,如果有人安装了您的项目,他们将获得带有错误 numpy 1.19.6 版本的 pandas 1.2.1 版本,并且你可能会因为您的软件冒出奇怪的错误而出现一些白发。因此,这个安装过程不是确定性的!

最可靠的方法是固定所有内容。锁定的依赖项的依赖项的依赖项的依赖项…,你会明白的。 锁定和兔子洞一样深。幸运的是,有一些工具可以为您实现这一目标。

注意:如果你正在构建一个可重用的包而不是一个典型的项目,你不应该如此激进地固定它(这就是为什么 Pandas 不固定到确切的 Numpy 版本的原因)。由封装的最终用户来决定是什么以及如何积极地固定被认为是最佳实践。如果您作为包创建者固定所有内容,那么您将关闭最终用户的大门。



如何固定 Python 依赖项?

每当您调用 pip install 将一些热门的新软件包放入您的项目时,您应该停下来想一想。这将为您的项目创建一个新的依赖项。我该如何记录?

您应该将新库及其版本号记入 requirements.txt 文件。这是 pip 理解的一种格式,可以一次安装多个包。

# requirements.txt

pandas==1.2.1
matplotlib==3.4.0
复制代码


# 安装

pip install -r requirements.txt
复制代码


这已经比人们遇到的大多数数据科学项目要好得多,但我们仍然可以做得更好。记住上一节关于版本固定的递归依赖兔子洞。那我们如何使安装更具确定性呢?

答案是 pip-compile 命令和 requirements.in 文本文件。

# Requirements.in

matplotlib==3.4.0
复制代码


# 自动生成 requirements.txt


pip-compile requirements.in
复制代码


# 生成的 requirements.txt

cycler==0.11.0
    # via matplotlib
kiwisolver==1.3.2
    # via matplotlib
matplotlib==3.4.0
    # via -r requirements.in
numpy==1.22.0
    # via
    #   matplotlib
    #   pandas
pandas==1.2.1
    # via -r requirements.in
pillow==9.0.0
    # via matplotlib
pyparsing==3.0.6
    # via matplotlib
python-dateutil==2.8.2
    # via
    #   matplotlib
    #   pandas
pytz==2021.3
    # via pandas
six==1.16.0
    # via python-dateutil
复制代码


requirements.in 中,您应该只放置您的直接依赖项。

然后,pip-compile 会将所有库完美地固定到 requirements.txt 中,它为确定性安装提供了所有信息。十分简单!请记住将这两个文件也提交到您的 git 存储库中。



如何固定 Python 版本?

固定 Python 版本很棘手。 如果不使用 conda 之类的工具,没有直接的方法来固定 Python 本身的版本依赖项

你可以从你的项目中创建一个 Python 包,它可以让你在 setup.py 或 setup.cfg 中使用键(Key) python_requires>=3.9 定义 Python 版本,但对于一个典型的数据科学项目来说,这有点过犹不及,因为它通常不具备可重用使用包的特性。

如果你真的很想固定到特定的 Python,你也可以在你的代码中做这样的事情:

import sys
if sys.version_info < (3,9):
    sys.exit("Python >= 3.9 required.")
复制代码


强制Python版本的最可靠的方法是使用Docker容器。

当您的项目足够成熟并提升到云和生产中时,您应该考虑固定整个环境而不仅仅是 Python 的东西。

这就是 Docker 容器是您最好的朋友的地方,因为它们不仅可以让您固定 Python 版本,还可以固定操作系统中的任何内容。它就像一个虚拟环境,但规模更大。


主要收获

  • 不要避免依赖管理 —- 当你把咖啡倒在你的 MacBook 上时,你未来的自己会欣赏记录在案的依赖关系。
  • 始终在本地计算机上使用虚拟环境 -- 当您安全地处于保护气泡中时,尝试使用带有 2 颗 GitHub 星的深奥 Python 库没什么大不了的。
  • 固定版本比不固定要好 -- 版本固定可以在项目不固定时防止包向前移动。
  • 包变化很大,Python 没那么多 -- 即使是单个包也可以有几十个嵌套的依赖项,而且它们在不断变化,但 Python 相对稳定且符合未来发展。


相关文章
|
3月前
|
机器学习/深度学习 数据采集 自然语言处理
Python编程的十大神奇依赖库
Python编程的十大神奇依赖库
|
6月前
|
Python
项目依赖的python包requirements.txt文件的生成与安装
项目依赖的python包requirements.txt文件的生成与安装
176 0
|
8月前
|
机器学习/深度学习 数据可视化 数据挖掘
为什么Python是数据科学家的首选语言
为什么Python是数据科学家的首选语言
36 0
|
2月前
|
分布式计算 DataWorks 关系型数据库
DataWorks常见问题之第三方Python依赖包使用失败如何解决
DataWorks是阿里云提供的一站式大数据开发与管理平台,支持数据集成、数据开发、数据治理等功能;在本汇总中,我们梳理了DataWorks产品在使用过程中经常遇到的问题及解答,以助用户在数据处理和分析工作中提高效率,降低难度。
|
3月前
|
开发者 Python
解码pip:Python项目依赖的得力助手
解码pip:Python项目依赖的得力助手
54 0
|
5月前
|
网络安全 C语言 Python
Python【问题 01】pip install MySQL-python==1.2.4b4 依赖安装问题记录及解决
Python【问题 01】pip install MySQL-python==1.2.4b4 依赖安装问题记录及解决
36 0
|
5月前
|
Serverless Python
在阿里函数计算中,你可以通过以下步骤在本地安装Python依赖
在阿里函数计算中,你可以通过以下步骤在本地安装Python依赖
65 1
|
5月前
|
Serverless Python
阿里函数计算中,你可以通过以下步骤在本地安装Python依赖
阿里函数计算中,你可以通过以下步骤在本地安装Python依赖
68 6
|
6月前
|
机器学习/深度学习 数据挖掘 Linux
如何在Python中使用虚拟环境管理依赖
当在Python中开发项目时,使用虚拟环境来管理依赖是一种良好的实践,可以隔离不同项目的依赖关系,避免冲突,并确保项目的稳定性。
|
8月前
|
Python
生成python依赖包文件
本文首先需要安装python环境,可以自行查阅文档,这里不再说明。 假如,我们有一个名为hello-flask的flask应用,该应用只依赖flask外部包。 有两种方式可以生成该应用的依赖包文件,分别介绍: