今年是 Anaconda 成立 10 周年,我们一直在花时间回顾作为一家公司以及作为 Python 开源开发社区的一部分取得的成就,以及思考我们未来的方向。还有很多事情要做,在这篇博文中,我将尝试提供一个快照,展示我们认为 Python 面临的一些新挑战以及 Anaconda 的开源开发工作将走向何方。
在深入探讨这样的广泛愿景文档之前,重要的是要承认其有限的视角。我想谈谈 Anaconda 开源软件 (OSS) 开发人员关注的问题,但这并非宣称这些是 Python 生态系统中所有人都应该关注的问题。OSS 在存在多种观点、优先事项和技能异步地探索软件可能性空间时效果最佳。我们中只需一个人发现一个好主意、编写一段有用的代码或编写一份优秀的文档,我们所有人都会从中受益。目标应该是找到一个可以让每个人的观点和技能都能产生积极影响的地方,这篇博文反映了我们认为 Anaconda 在帮助推动开源 Python 发展方面具有良好定位。
是什么让 Python 如此出色?
在讨论我们希望在未来 10 年的 Python 中看到什么之前,我想先停下来讨论为什么我们希望 Python 继续成为一种流行语言。Python 由于各种原因在广泛的编程用例中占据主导地位。
-
对于非传统程序员来说,它足够容易学习。
-
它足够强大和灵活,让专家能够创建复杂的软件。
-
对于不同软件开发专业知识水平的人来说,存在从 Python 用户到 Python 生态系统贡献者的路径。
-
它可以在所有主要台式机操作系统上轻松使用,并且可以在许多平台上轻松移植。
-
各个领域的领域专家为他们自己和同事构建专门的软件包。
-
Python 易于与其他软件接口,无论是加载其他语言的编译库、通过网络与服务器通信,还是使用传统的命令行脚本进行系统编排。
当然,Python 也存在一些不足之处,但它在满足这些理想方面已经足够成功,成为世界上最顶尖的语言之一。我们希望利用这些优势,继续推动 Python 成为任何人在任何地方都可以使用的计算工具,这是一个挑战,因为存在大量的“任何人”和“任何地方”,如果 Python 不探索一些新方向,就会错过这些地方。
Python 面临哪些新挑战?
随着我们拥有越来越多的计算选择,将 Python 打造成“任何人在任何地方都可以使用”的目标变得越来越难。在 Python 存在的大部分时间里,大多数开发人员只需要担心少数几种芯片供应商和操作系统,新平台的出现速度很慢,更奇特的系统架构通常只对少数专家开发人员和用户可用。一些技术趋势已永久打破了这种现状,尽管许多 Python 开发人员一直在努力使 Python 适应新现实,但仍然有很多工作要做。
趋势 #1 - 硅的进化爆炸
在微型计算机的大部分历史中,我们可以依靠硬件性能逐年提高,而无需对我们编写的软件进行任何根本性更改。在 21 世纪初,这种现象不再适用,因为多核中央处理单元 (CPU) 从奇特转变为实际上必须具备的,才能继续提高通用 CPU 的性能。从那时起,我们见证了芯片专业化的兴起,以从固定的功耗预算中挤出更多性能,包括诸如矢量指令集、图形处理单元 (GPU)、AI 加速器、片上硬件加速视频编解码器以及大量试图将其他新颖想法推向市场的芯片初创企业。
从某种意义上说,Python 作为一种高级解释语言,能够编写在许多不同的芯片架构上运行的代码非常棒,只要有人完成了移植 Python 解释器和重新编译所有必需的 Python 扩展模块的繁重工作。但是,相同的 Python 解释器在其中内置了许多假设,这使得多核 CPU 的使用变得具有挑战性,并且没有直接提供任何帮助来利用现有的多种专用加速器技术(如 GPU)。这项工作已经落到了蓬勃发展的 Python 模块生态系统中,但每个模块基本上都必须从头开始构建自己的编译器基础设施来支持这些新的计算形式。对于大多数较小的 Python 项目来说,添加加速计算支持仍然非常困难。
趋势 #2 - 计算机和集群的模糊界限
对我们大多数人来说,我们编程的对象是一台单独的“计算机”,我们将其想象为在 CPU 上运行的操作系统,它可以访问三个位置之一的数据:RAM、“磁盘”(SSD 或其他)和网络。RAM 比磁盘快得多,磁盘也比网络快得多。对于计算密集型工作负载,我们通常会忽略磁盘和网络的速度,因为它们是一次性启动成本,并将 RAM 想象成一个速度一致的数据源,无论它在内存中的布局方式如何,也不管哪个 CPU 内核正在访问它。数据要么“在内存中”,要么不在内存中,我们不需要担心除了这些之外的任何其他事项。
实际上,计算机架构更加多样化和复杂。我们拥有具有大量 CPU 内核的服务器,这些内核对内存的访问速度不一致,可能有多级非易失性内存,具有不同的速度和延迟特性,以及带有自己的内存系统和互连策略的加速器(如 GPU),以及极快且延迟极低的网络技术。计算机的内部越来越像一个集群,资源通过令人眼花缭乱的总线技术连接在一起。另一方面,高性能网络和集群编排工具正在使机架或数据中心中服务器之间的界限更加模糊。因此,关键是要拥有 Python 工具(例如 Dask,仅举一例),这些工具可以让用户轻松地将计算划分为多个计算域,管理数据位置,并在可能的情况下将计算转移到数据附近。
趋势 #3 - 云计算成为主流
在 Anaconda 的早期(当时我们还被称为 Continuum Analytics),我与企业客户讨论的常见话题之一是他们是否以及何时将一些工作负载迁移到云计算服务。这些时间表通常是在模糊的未来,但现在这种过渡时期已经基本过去。云计算现在已成为每个组织 IT 战略的一部分(即使只是作为混合方法的一部分),并且云技术已经渗透到许多个人开发人员和研究科学家的工具箱中(例如,参见 Pangeo)。
这一趋势并未给 Python 本身带来太多新的挑战,因为大多数云 API 已经与出色的 Python 库配对。相反,云计算降低了使用来自趋势 #1 和 #2 的所有新技术的资本成本。使用信用卡,任何人都可以在几分钟内获得一台服务器或整个集群,这些服务器或集群拥有最先进的 CPU、内存和网络技术。唯一阻止此类用户从这种出色的硬件中获益的是他们的软件堆栈的灵活性以及他们将代码移植到实际利用它(或缺乏这种能力)的难易程度。
趋势 #4 - 个人计算机的消亡与重生
在 Anaconda Distribution 首次创建时,最难解决的问题是在 Windows、Mac 和 Linux 上构建和运行最流行的 Python 数据科学软件包。尽管在各个方面不兼容,但这三种台式机操作系统比它们的不同之处更相似。Python 非常适合 UNIX 风格的命令行、文件、套接字、进程和线程的世界,这些世界以某种形式存在于每个流行的台式机操作系统中。除了某些注意事项外,Python 用户可以在任何一个平台上进行开发时感到宾至如归。
然而,过去十年,计算领域发生了巨大转变。越来越多的人开始使用“个人电脑”,但它们已不再是 Python 诞生的传统“PC”。现在,最常见的个人计算系统是手机、平板电脑和 Chromebook。即使在台式机系统上,大多数用户也花费大量时间使用网页浏览器。因此,2022 年最流行的软件平台是 (1) 网页和 (2) iOS 和 Android 等移动操作系统。这些新平台的显著特征是它们与传统的桌面操作系统有根本的不同。它们对文件和网络访问施加了严格的安全限制,默认情况下没有内置命令行界面,并且软件分发机制对于习惯编写 Python 脚本的人来说完全陌生。然而,网页浏览器和移动设备正是下一代 Python 用户需要学习编码和分享作品的地方。我们该如何赋予他们这些工具呢?
我们如何帮助 Python 应对这些挑战呢?
我们无法用一个神奇的解决方案来解决这些挑战,而是需要几个相互补充的战略方向,这些方向相互支持。我们在 Anaconda 已经确定了五个领域,我们认为我们在这个领域拥有强大的影响力。每一个领域都比任何单个开源项目都要大,但我会在过程中提到一些示例项目。这份清单不会涵盖所有内容,也不意味着我们认为其他项目没有解决这些问题。我们将需要来自不同群体多种方法来应对我们面前的挑战。
战略 #1 - 我们需要更多编译器,既有广泛的,也有专门的。
将人类可读的程序映射到硬件可执行的机器代码的关键工具是编译器。我们可能会认为 Python 作为一种解释型语言,在最常见的实现中不需要关心编译器,但我们已经看到编译器技术对于提高 Python 性能至关重要。但 Python 不需要一个单一的通用编译器,它需要一整套编译器工具来满足不同的需求。
在最广阔的范围内,我们希望看到 Python 解释器能够包含即时编译方法,以消除执行动态类型语言的某些开销。正如许多人指出的,Python 的设计使得这非常具有挑战性,但我们还有很多可以为大多数 Python 用户做的事情。像微软正在进行的 更快 CPython 工作,以及 Pyston 和 PyPy 等项目,都在使用各种编译器技术来尝试加速所有 Python 程序。在这方面可以做更多工作,不仅限于单线程性能。我们还认为 nogil CPython 分支非常有前景,并希望看到它的想法被整合到 Python 解释器中。
除了改进 Python 解释器的广阔方法之外,还有一些空间可以为解决特定领域或独特硬件目标的更专注的编译器。例如,Anaconda 已经与 PyData 社区一起开发了 Numba,至今已有十年之久,并且已被广泛的用户用于进行科学和数值计算。Numba 专注于数值计算,主要使用 NumPy 数组,使其能够在用户代码上实现极其高的加速(从 2 倍到 200 倍)。我们已经看到了 Numba 有限范围和可扩展性允许它移植到非 NumPy 数据结构以及新硬件目标的各种方法。我们认为这个想法可以进一步推动,激发人们创建一套模块化组件,用于提前编译和即时编译(以及混合!)用例。这将进一步扩展编译器方法在生态系统中的采用,使 Numba 成为 Python 项目中使用的广泛编译器类别中的一个例子。
请注意,与编译器讨论紧密相关且非常相关的是分发编译后的软件。我们仍然相信 conda 将非常重要,因为我们需要能够将各种编译库和应用程序(不仅仅是 Python)交付给越来越多的平台。其中一些平台将非常不寻常,例如网页浏览器和嵌入式系统,因此 conda 的功能需要不断发展。
战略 #2 - 扩展我们的数据模型工具箱。
像 Numba 和 Dask 这样的项目成功的其中一个未被充分重视的方面是,它们的创建依赖于像 NumPy 和 pandas 这样的项目在之前被广泛采用。这些项目为 Python 用户提供了一种共同的词汇和心智模型,用于以多维数组(NumPy)或数据帧(pandas)的形式批量处理数据。在 Dask 的情况下,这些高级 API 通常非常适合并行计算,可以直接移植到 Dask 的容器 API。这意味着 NumPy 或 pandas 用户可以切换到 Dask,将他们的计算并行化到数十个节点,而实际上并不需要学习太多新概念。在 Numba 的情况下,使用 NumPy 的好处更加底层。由于 NumPy 数组具有一个明确的、简单的内存布局,因此像 Numba 这样的工具可以动态生成高效的机器代码来处理 NumPy 数组,而对于作为 Python 对象集合存储的数据来说,这是不可能的。如果没有广泛使用 NumPy 数组作为操作数值数据的标准方式,Numba 想要在生态系统中获得广泛采用将更加困难。
数组和数据帧一直是过去十年的主要关注点,但还有其他类型的数据存在。我们最近更多地参与了促进 Python 生态系统中其他数据模型的项目,例如 Awkward Array 项目。Awkward Array 来自高能物理学界,需要处理大型半结构化数据集,这些数据集具有大小可变的嵌套列表和缺失数据。这种类型的数据使用 NumPy 数组或 pandas 数据帧非常“笨拙”(因此得名),但在各种应用程序中都可见。同样,我们也一直在努力改进稀疏矩阵的采用,尤其是来自 GraphBLAS 的扩展定义。GraphBLAS 试图使用线性代数的语言创建图算法的标准构建块。我们认为 GraphBLAS 这样的工具在 Python 生态系统中具有很大的潜力,它们的应用将使未来对稀疏和不规则形状数据的并行化和扩展计算工作变得更加容易。
战略 #3 - 计算机是一个集群,集群是一台计算机。
感谢像 Dask(以及其他几个项目)这样的项目,Python 拥有一套强大的工具,可以在计算机集群上处理大型数据集。这些工具的本质是将数据集划分为独立的部分,最大限度地减少数据移动,并在可能的情况下将计算带到数据所在的位置。这使得在通信延迟和带宽是重要限制的世界上能够高效地扩展。同时,这些工具为集群提供了非常有用的抽象层,允许用户将它编程为一个单一系统,让调度器决定如何以及在哪里执行代码。使分布式计算范式尽可能简单将继续是 Anaconda 的一项持续目标。
将一台计算机编程为一个集群同样有价值。在硬件级别,这已经有些真实,因为系统可以由多个 CPU 内核组成,这些内核具有“首选”内存区域,在这些区域中访问速度更快。此外,计算可能发生在服务器上的加速器设备(如 GPU)中,这些设备拥有与 CPU 不同的内存。然而,对于 Python 来说比较独特的是,最大的问题是 Python 中的全局解释器锁限制了即使是编译扩展也无法在具有单个 Python 进程的高核心计数系统中充分利用。从长远来看,我们需要解决像全局解释器锁(GIL)(不仅仅是 GIL!)这样的问题,这些问题阻碍了 Python 在多线程工作负载中的发展。在此期间,像 Dask 这样的工具提供了一个很好的临时解决方案,即在一个系统上启动一组 Python 进程并将工作分配给它们。Dask 的轻量级架构非常适合在单个计算机上使用,但我们可以玩一些额外的技巧来使“单一系统集群”用例更有效率。考虑到云中大型服务器的可用性,我们认为提高 Python 在高核心计数服务器上的效率具有巨大的潜力。
战略 #4 - 网络就是你的数据湖。
之前的大部分讨论都集中在计算方面:如何描述计算、如何加速计算以及如何在多台计算机上划分计算。同样重要的是,但很少有人讨论的是等式的 I/O 方面。你的数据在哪里,你如何方便快捷地加载它?
最明显的答案是将所有数据放在一个地方,并使用少量文件格式。这种标准化是一个有吸引力的选择,一些组织可以花费必要的资源来创建和执行数据湖的一致使用。然而,许多组织(以及大多数个人)没有能力完全执行数据湖,这使得数据工作者不得不处理跨多个不同系统和文件格式的众多数据源。事实上,能够快速将新的数据源集成到分析中,而无需等待适当的数据湖集成,对于某些群体来说可能是竞争优势。
正如我们押注计算异构性一样,我们也押注数据异构性。数据将存在于它存在的地方,虽然集中和组织数据是许多群体的值得追求的目标,但这项任务永远不会完成,工具需要承认这一现实。为此,我们正在开发许多项目,旨在让 Python 用户轻松访问尽可能广泛的数据存储系统和文件格式。 Fsspec 已经成为许多项目(包括 Dask)中流行的文件系统类抽象层,它允许将本地存储的文件、云中的对象存储(如 S3)或各种服务器 API(如 Google Drive)中的文件都以相同的方式处理。在这些抽象层之上,我们创建了 Intake,它提供了一个灵活的插件架构和一个轻量级的基于 YAML 的数据源目录规范。Intake 旨在与 NumPy 和 pandas 这样的工具以及 Dask 这样的用于大型分布式工作负载的工具一样有效地工作。
我们最近添加到数据访问领域的是一个名为 Kerchunk 的项目,它允许索引通常没有为高效云计算设计的存档数据格式。Kerchunk 可以扫描各种格式(如 NetCDF、TIFF 等)中的一组潜在的大文件,并构建数据的元数据索引,以使现代工具(如 Xarray)能够更有效地访问这些数据,而无需首先对数据进行转码。能够使所有数据(即使是旧数据)在云环境中易于使用是我们 Python 战略的关键部分。
战略 #5 - 拥抱后 PC 时代。
十年前,许多 PyData 开发人员倾向于忽略他们个人不使用的平台,通常是 Windows。资源稀缺,许多维护人员是志愿者,所以他们为什么要关注一个他们不熟悉且难以测试的平台呢?这并不是一种不合理的做法,但如果不是少数爱好者(向 Christoph Golke,以及其他所有人致敬)的努力,那么大量用户将被排除在 Python 生态系统之外,他们让 Windows 在 PyData 上的支持得以延续。当我在 Anaconda 展位工作时,Anaconda 的 Windows 用户是我在会议上遇到的最感谢的用户。最终,具有 Windows、macOS 和 Linux 支持的免费持续集成服务的出现使得所有三大桌面操作系统在 PyData 生态系统中几乎平等地存在。
我认为我们再次站在了犯下 Windows 级错误的边缘,将网页浏览器和移动操作系统视为“太奇怪”,无法成为一流的 Python 平台。当然,这些平台的限制比 Windows 和 Linux 之间的差异要大得多。尽管如此,对于这些平台作为主要计算平台的用户数量是巨大的。我们需要跳进去,弄清楚 Python 在这些平台上应该是什么样子,否则将会有一代计算机用户错过了 Python 生态系统提供的许多优秀事物。
现在,我们不必从头开始。多年来,由于像 Jupyter(以及有影响力的旧项目,如 Sage)这样的“笔记本”项目,Python 一直在浏览器中可见。Jupyter 提供了一个基于浏览器的前端,用于在内核(通常是 Python)中运行代码,该内核在浏览器之外执行。Python 内核作为普通应用程序在某处运行,无论是在用户的计算机上还是远程服务器上,并通过 WebSocket 与基于 Web 的前端通信。这种架构巧妙地避开了在网页浏览器中执行代码的所有限制,但这意味着 Jupyter 笔记本并不真正自包含。我可以查看笔记本,但除非我在某处创建 Python 环境并启动 Jupyter 来加载笔记本,否则我无法与之交互。
我们将 Python 连接到浏览器的悠久历史也包括我们帮助创建和推广的数据可视化项目堆栈,例如 Bokeh、Datashader、HoloViz 和 Panel。这些项目旨在让 Python 开发人员能够在网页浏览器中创建实时交互式数据可视化,而无需成为完全新的前端技术堆栈的专家。我们已经看到许多用户在能够从 Python 针对浏览器进行开发时创建了惊人的事物。
但是,如果我们能够更进一步,将 Python 运行时本身推入浏览器呢?实际上,JupyterLite 已经在为笔记本做这件事了!更广义地说,如果我们将 Python 视为浏览器中的头等语言,并利用我们已经拥有的庞大 Python 包库,我们可以构建很多很棒的东西。沿着这些思路,我们对 WebAssembly 将许多语言社区(不仅仅是 Python)带到浏览器的潜力非常感兴趣。Python 已经是台式机上许多语言和库之间的通用粘合剂。将其放入浏览器(使用像 Pyodide 和 PyScript 这样的项目)现在有可能将 Python 世界中最好的包与 Javascript 粘合在一起。这项工作将充满挑战,并且在浏览器安全模型的限制范围内,许多事情根本不可能实现,但即使浏览器对 Python 可以做到的某些或大部分内容的支持,也能让许多伟大的应用程序得以构建。
对于移动操作系统,情况稍微简单一些。iOS 和 Android 比网页浏览器更接近 macOS/Linux,Python 可以运行的修改少得多。这里的大多数挑战都与为本机接口(GUI 和其他平台服务)提供 Python 接口以及自动化将应用程序打包到各种应用程序商店中不熟悉的流程有关。这是一个像 BeeWare 这样的项目非常令人兴奋的地方,它的子项目解决了每一个问题:Toga(GUI)、Rubicon(本机 API 桥接)和 Briefcase(应用程序打包)。BeeWare 中烘焙的平台知识越多,任何技能水平的 Python 开发人员将原型变成应用程序并与更广泛的受众分享就越容易。
我们能做到吗?
简而言之,可以!过去十年中 PyData 生态系统的爆炸式增长使今天的 Python 用户获得了 2012 年难以想象的功能和特性。浏览器中的交互式数据可视化、Python 中的 GPU 加速计算以及 Jupyter 笔记本中轻松的分布式计算,在当时似乎是遥不可及的目标,但现在已经成为现实。想象一下,在另一个十年中,我们可以用比当时更大的社区做些什么。
但是,我们必须一起努力。本文中描述的想法将成为 Anaconda 的 OSS 工作的重点,但如果我们的小团队是唯一一个致力于这些想法的团队,这些想法将无法实现其潜力。我们希望其他人也受到启发来解决这些领域,无论是通过加入我们进行关键项目,还是自己尝试新的想法。只要我们专注于各自的优势,继续扩大贡献者社区,并互相学习,就会发生伟大的事情!
注意:这篇文章最近被改编并发布在 The New Stack 上。