工具链路线图#

SciPy 库的运行需要(或可选依赖于)其他几个库,主要的依赖是 Python 和 NumPy。构建该库或构建文档则需要更大范围的库和工具集。

当然,工具和库本身并非一成不变。本文旨在指导 SciPy 如何随时间推移使用这些动态依赖。

SciPy 旨在与多个版本的依赖库和工具兼容。强制用户群在每个发布版本都升级其他组件会大大降低 SciPy 的价值。然而,维护与非常旧的工具/库的向后兼容性,会限制可以整合的新功能和能力。SciPy 采取了相对保守的方法,在主要平台上维护与多个主要版本的 Python 和 NumPy 的兼容性。(这本身可能会施加进一步的限制。请参阅 C 编译器部分以获取示例。)

  • 首先,SciPy 是一个 Python 项目,因此它需要一个 Python 环境。

  • 需要安装 BLAS 和 LAPACK 数值库。

  • 需要 C、C++、Fortran 代码的编译器,以及 Cython 和 Pythran 的编译器(后者目前是可选退出)

  • Python 环境需要安装 numpy 包。

  • 测试需要 pytesthypothesis Python 包。

  • 构建文档需要 matplotlib、Sphinx 和 MyST-NB 包,以及 PyData 主题。

用于构建 CPython 的工具对构建 SciPy 所用的工具也有影响。它也对文档中使用的示例(例如,函数的 docstring)有影响,因为这些示例只能使用所有受支持配置中存在的功能。

构建 SciPy#

Python 版本#

SciPy 与多个 Python 版本兼容。在放弃对旧 Python 版本的支持时,SciPy 遵循 [NEP29] 的指导。通常,对最旧 Python 版本的支持会在原始发布后 42 个月停止。在 PEP 602 被接受后,这主要发生在四月,并由 SciPy 的年中发布版本采纳。

Python 版本支持随时间变化

从 SciPy 1.3 开始,已停止支持 Python 2.7。

日期

支持的 Python 版本

2025

Py3.11+

2024

Py3.10+

2023

Py3.9+

2022

Py3.8+

2021

Py3.7+

2020

Py3.6+

2019

Py3.5+

2018

Py2.7, Py3.4+

NumPy#

SciPy 依赖于 NumPy,但 SciPy 的发布版本与 NumPy 的发布版本不绑定。SciPy 尝试至少与 NumPy 的前 4 个发布版本兼容。特别是,SciPy 不能只依赖最新 NumPy 的特性,而需要使用这 4 个 NumPy 版本中通用的特性来编写。

每个 SciPy 版本的 Python 和 NumPy 版本支持

该表格显示了适合每个 SciPy 次要版本的 NumPy 和 Python 版本。请注意,并非特定 SciPy 次要版本的所有补丁版本都支持所有列出的 Python 版本。只有每个次要版本中最新的补丁版本才保证支持所有列出的 Python 版本。

SciPy 版本

Python 版本

NumPy 版本

1.15

>=3.10, <3.14

>=1.23.5, <2.5.0

1.14

>=3.10, <3.14

>=1.23.5, <2.3.0

1.13

>=3.9, <3.13

>=1.22.4, <2.3.0

1.12

>=3.9, <3.13

>=1.22.4, <2.0.0

1.11

>=3.9, <3.13

>=1.21.6, <1.27.0

1.10

>=3.8, <3.12

>=1.19.5, <1.26.0

1.9

>=3.8, <3.12

>=1.18.5, <1.26.0

1.8

>=3.8, <3.11

>=1.17.3, <1.24.0

1.7

>=3.7, <3.11

>=1.16.5, <1.23.0

1.6

>=3.7, <3.10

>=1.16.5, <1.21.0

1.5

>=3.6, <3.10

>=1.14.5, <1.20.0

1.4

>=3.5, <3.9

>=1.13.3, <1.18.0

1.2

2.7, >=3.4, <3.8

>=1.8.2, <1.17.0

在特定情况下,例如特定架构,这些要求可能会有所不同。请查阅 发布说明 和元包 oldest-supported-numpy 以获取更多信息 [OSN]

编译器#

构建 SciPy 需要 C、C++、Fortran 编译器,以及 Python 转换器 Cython 和 Pythran(后者从 1.7.0 版本开始是可选依赖)。

为了与大量平台和设置保持兼容性,特别是在无法使用官方 wheel 包(或其他分发渠道如 Anaconda 或 conda-forge)的情况下,SciPy 尝试在尚未达到官方生命周期结束的平台上保持与旧编译器的兼容性。

如下文更详细解释,当前最低编译器版本为

编译器

默认平台(已测试)

次要平台(未测试)

最低版本

GCC

Linux

AIX, Alpine Linux, OSX

GCC 9.x

LLVM

OSX

Linux, FreeBSD, Windows

LLVM 12.x

MSVC

Windows

Visual Studio 2019 (vc142)

请注意,目前没有专门的 CI 任务来测试最低支持的 LLVM/Clang 版本。比 SciPy CI 中使用的旧版本应该也能工作,只要它们支持核心(非标准库)C++17。如果您在编译过程中遇到问题,请提交问题。

官方构建#

目前,SciPy wheel 包的构建方式如下

平台

CI 基础 镜像

编译器

备注

Linux x86

ubuntu-22.04

GCC 10.2.1

cibuildwheel

Linux arm

docker-builder-arm64

GCC 11.3.0

cibuildwheel

OSX x86_64 (OpenBLAS)

macos-12

Apple clang 13.1.6/gfortran 11.3.0

cibuildwheel

OSX x86_64 (Accelerate)

macos-13

Apple clang 15.0.0/gfortran 13.2.0

cibuildwheel

OSX arm64 (OpenBLAS)

macos-14

Apple clang 15.0.0/gfortran 12.1.0

cibuildwheel

OSX arm64 (Accelerate)

macos-14

Apple clang 15.0.0/gfortran 13.2.0

cibuildwheel

Windows

windows-2019

GCC 10.3.0 (rtools)

cibuildwheel

请注意,OSX wheel 包还附带了 gfortran 11.3.0(适用于 x86_64)和 gfortran 12.1.0(适用于 arm64)。详见 tools/wheels/cibw_before_build_macos.sh

C 编译器#

SciPy 与大多数现代 C 编译器兼容(特别是 clang)。如今,所有相关编译器对最新的 C 语言标准都有合理的支持,尽管这与过去的情况大相径庭。以下段落主要讨论这些约束的演变;不关心历史背景的读者可以跳到最后的表格部分。

ABI、编译器支持与 C 标准的历史背景

过去,在相关平台上,对 C 语言支持方面限制最大的编译器是 Microsoft Visual C++ 编译器和工具集(统称为 MSVC;它有一个复杂的版本方案[MSVC]。直到 Visual Studio 2013,每个 MSVC 版本都附带一个与之前版本不兼容的 C 运行时 (CRT) 库。

这种应用程序二进制接口 (ABI) 兼容性的缺乏意味着所有希望通过此接口进行通信的项目(例如从共享库调用函数)都需要使用相同的 MSVC 版本进行(重新)编译。CPython 2.7 的长期支持意味着 Python 本身在很长一段时间内都停留在 VS 2008(为了不在补丁发布中破坏 ABI),因此 SciPy 也停留在该版本。

使用 VS 2008(不支持 C99)为 CPython 2.7 编译构建版本,这意味着 SciPy 中的 C 代码长期以来必须符合早期的 C90 语言和标准库标准。在 SciPy 1.3.x 中放弃对 CPython 2.7 的支持后,该限制最终被解除(尽管最初只是逐步解除)。

自 Visual Studio 2015 发布以来引入的“通用 C 运行时”[UCRT],C 运行时的 ABI 一直保持稳定,这意味着 SciPy 必须使用与底层 CPython 版本相同的编译器版本的限制不再适用。然而,这种稳定性并非无限期:微软已经计划了一个会破坏 ABI 的发布版本——跨编译器和 C/C++ 标准库——(暂定名为“vNext”),但目前尚不清楚何时发布。一旦发生这种情况,SciPy 将再次被限制在最多支持最后一个 ABI 兼容的 Visual Studio 版本(目前是 VS 2022),直到根据 NEP29 支持的所有 CPython 版本都已用 vNext 兼容的编译器在上游构建。

更具体地说,Microsoft Visual Studio 版本与目标“工具集”版本之间存在区别,“工具集”定义为“Microsoft C++ 编译器、链接器、标准库和相关实用程序”。每个 Visual Studio 版本都附带一个默认的 MSVC 工具集版本(例如 VS2017 附带 vc141,VS2019 附带 vc142),但即使在较新版本的 Visual Studio 中,也可能针对较旧的工具集。由于编译器的性质(即分为前端和后端),支持给定特性(例如 C 语言中的特性)的限制因素是 Visual Studio 版本还是工具集版本取决于具体情况,但通常后者是更难逾越的障碍,因此是有效的下限。

这是因为虽然 ABI 在工具集版本之间保持兼容(直到 vNext),但所有链接操作都必须使用至少与用于构建任何相关构件的工具集一样新的工具集,这意味着工具集版本升级往往具有“传染性”,即:要求所有使用它的库也升级其工具集(以及可能的编译器)版本。这对 NumPy 来说比 SciPy 更是一个问题,因为后者只有很小的 C API,并且被远少于 NumPy 的项目所编译。此外,使用更新的工具集意味着编译 C++ 代码的库(如 SciPy)的用户可能还需要较新的 Microsoft Visual C++ 可再发行组件,这可能需要分发给他们。

总而言之,每个 SciPy 版本对 MSVC 编译器或工具集的最低要求主要由当时支持的最旧 CPython 版本决定。第一个将最低要求提高到超出此范围的 SciPy 版本是 SciPy 1.9,原因是包含了 HiGHS 子模块,它无法用 vc141 编译(并且公共 CI 中积极移除 VS2017 使得继续确保所有地方都使用非默认工具集版本变得不可行)。

SciPy 版本

CPython 支持

MS Visual C++

工具集版本

直到 1.2

2.7 & 3.4+

VS 2008 (9.0)

vc90

1.3, 1.4

3.5+

VS 2010 (10.0)

vc100

1.5

3.6+

VS 2015 (14.0)

vc140

1.6, 1.7

3.7+

VS 2017 (14.1)

vc141

1.8

3.8+

VS 2017 (14.1)

vc141

1.9

3.8+

VS 2019 (14.20)

vc142

就 C 语言标准而言,值得注意的是 C11 具有可选特性(例如原子操作、线程),其中一些(VLA 和复数类型)在 C99 标准中是强制性的。C17(有时也称为 C18)可以被认为是 C11 的一个错误修正,因此通常可以完全跳过 C11。

SciPy 在使用更高级语言特性方面受到可用编译器支持的限制,特别是微软在实现 C99/C11/C17 的符合性方面花费了很长时间,然而从 Visual Studio 16.8 开始,C11/C17 得到了支持(尽管不包括 C11 的可选特性)。C99 的 <complex.h> 支持对于 SciPy 来说尤其有意义。但是,在 Windows 上仍然可以使用复数类型,前提是使用Windows 特定的类型

因此,只有在 Windows 上有支持的情况下,才能使用 C90 之外的 C 特性;然而,截至 2021 年底,已经使用了足够新的编译器。这是因为 GCC 和 LLVM 支持所有相关的 C11 特性,即使是目前使用的最旧版本,而 C17 只是 C11 的一个错误修正,如上所述。简而言之

日期

C 标准

<= 2018

C90

2019

旧代码使用 C90,新代码可考虑 C99

2020

C99 (不含 <complex.h>, <stdatomic.h>, <threads.h> 及 VLA)

2021

C17 (不含 <complex.h>, <stdatomic.h>, <threads.h> 及 VLA)

?

C23, <complex.h>, <stdatomic.h>, …

C++ 语言标准#

SciPy 的 C++ 语言标准通常是指导方针,而非官方决定。这尤其适用于试图预测新标准的采纳时间表。

日期

C++ 标准

<= 2019

C++03

2020

C++11

2021

C++14

2022

C++17 (核心语言 + 通用可用的标准库特性)

?

C++17 (完整标准库), C++20, C++23, C++26

因 manylinux 导致的编译器约束历史背景

自从停止支持 Python 2.7 以来,C++11 就可以普遍使用;而自从停止支持 Python 3.6 以来,Visual Studio 版本(之前因与 CPython 的 ABI 兼容性而停留在 14.0)已足够新,甚至可以支持 C++17。

由于官方构建(见上文)使用了相当新的 LLVM 版本,因此 C++ 支持的瓶颈在于支持的最旧 GCC 版本,SciPy 主要受到最旧支持的 manylinux 版本和镜像中版本的限制 [MANY]

在 2021 年底(随着 manylinux1 wheel 包的最终移除),GCC 的最低要求提升到 6.3,该版本完全支持 C++14 [CPP]。这对应于相关 manylinux 版本中存在的最低 GCC 版本,尽管这仍然考虑了基于 Debian 的“异类”manylinux_2_24,它与之前基于 RHEL 衍生 CentOS 的 manylinux 镜像(可以受益于“RHEL Dev Toolset”中 ABI 兼容的 GCC 后向移植)不同,它停留在 GCC 6.3。该镜像未能流行起来,很大程度上是因为这些过时的编译器,并于 2022 年年中达到了其生命周期结束。由于不同的原因,manylinux2010 也大约在同一时间达到了其生命周期结束。

剩余的镜像 manylinux2014manylinux_2_28 目前分别支持 GCC 10 和 12。后者将随着新的 GCC 版本作为后向移植可用而继续接收更新,但前者可能不会改变,因为 CentOS 项目不再响应发布 GCC 11 的 aarch64 后向移植

这使得所有主要平台及其编译器都处于相对较新的版本。然而,SciPy 历史上也一直努力支持较不常见的平台——如果不是通过二进制构件(即 wheel 包),那么至少通过保持可从源代码编译——这其中包括例如 AIX、Alpine Linux 和 FreeBSD。

平台支持和编译器上的其他约束

对于 AIX 7.2 和 7.3,默认编译器是 GCC 10(AIX 7.1 已于 2023 年 EOL),但 GCC 11/12 可以并行安装,类似地,AIX 也有基于 LLVM 17 的 Open XL

目前支持的最旧的 Alpine Linux 版本是 3.16,并且已经自带 GCC 11。对于 FreeBSD,目前支持的最旧的 13.x 版本附带 LLVM 14(并且 GCC 13 可作为 freebsd-port 使用)。

最后是关于哪些机器被广泛用于因其他原因(例如 SciPy 开发者,或出于性能原因希望自行编译的人)需要从源代码编译 SciPy 的人。最旧的相关发行版(没有 RHEL 风格的后向移植)是 Ubuntu 20.04 LTS(它有 GCC 9 但也有 GCC 10 的后向移植;Ubuntu 22.04 LTS 有 GCC 11)和 Debian Bullseye(有 GCC 10;Bookworm 有 GCC 12)。这是确定编译器支持下限的最弱限制(高级用户和开发者可以预期至少会保持他们的系统部分更新,或在可用时使用后向移植),并且随着旧发行版的使用数量减少,这逐渐变得不那么重要。

所有目前支持的最低编译器版本(GCC 9, LLVM 14, 带 vc142 的 VS2019)都完全支持 C++17 核心语言,因此可以无条件使用。然而,截至 2024 年年中,对整个 C++17 标准库的支持尚未在所有编译器中完成 [CPP],特别是 LLVM。因此,在使用任何给定的标准库特性之前,有必要检查它是否被所有编译器支持,然后才能在 SciPy 中使用。

C++20 的支持正在非常缓慢地稳定下来,即使抛开模块、协程和一些尚未普遍支持的标准库特性。鉴于 C++20 标准是一个如此大的发布版本,预计在我们可以开始考虑提升我们的基线之前,还需要一段时间。C++23 和 C++26 的编译器支持仍在大量开发中 [CPP]

Fortran 编译器#

通常,任何维护良好的编译器都可能适合并可用于构建 SciPy。话虽如此,我们不测试旧的 gfortran 版本,这就是为什么我们将下限与上面 GCC 的下限匹配的原因。

工具

版本

gfortran

>= 9.x

ifort/ifx

最新版本(未在 CI 中测试)

flang (LLVM)

>= 17.x

Cython 和 Pythran#

SciPy 始终需要一个最新的 Cython 编译器。自 1.7 版本起,Pythran 成为一个构建依赖(目前可以选择退出)。

OpenMP 支持#

由于各种原因,SciPy 不能随内置的 OpenMP 支持一同分发。在使用可选的 Pythran 支持时,从源代码构建时可以生成启用 OpenMP 的并行代码。

其他库#

任何符合 BLAS/LAPACK 接口的库都可以使用。已知 OpenBLAS、ATLAS、MKL、BLIS 和参考 Netlib 库均可工作。

最低版本

LAPACK

3.7.1

BLAS

OpenBLAS、MKL 或 ATLAS 的最新版本。Accelerate BLAS 库不再受支持。

还有一些额外的可选依赖。

版本

URL

mpmath

最新

http://mpmath.org/

scikit-umfpack

最新

https://pypi.ac.cn/project/scikit-umfpack/

pooch

最新

https://pypi.ac.cn/project/pooch/

此外,SciPy 支持与其他库的交互。安装这些库时,测试套件会运行额外的兼容性测试

工具

版本

URL

pydata/sparse

最新

pydata/sparse

测试与基准测试#

测试和基准测试需要最新版本的

工具

版本

URL

pytest

最新

https://pytest.cn/en/latest/

Hypothesis

最新

https://hypothesis.readthedocs.io/

asv (airspeed velocity)

最新

https://asv.readthedocs.io/

构建文档#

工具

版本

Sphinx

任何能工作的最新版本。>= 5.0。

PyData Sphinx 主题

任何能工作的最新版本。>= 0.15.2。

Sphinx-Design

任何能工作的最新版本。>= 0.4.0。

numpydoc

任何能工作的最新版本。>= 1.5.0。

matplotlib

通常建议 >= 3.5。

MyST-NB

任何能工作的最新版本。>= 0.17.1

jupyterlite-sphinx

任何能工作的最新版本。>= 0.17.1

jupyterlite-pyodide-kernel

任何能工作的最新版本。>= 0.1.0

注意

开发者注意:所需的 numpymatplotlib 版本对 Python docstring 中的示例有影响。示例必须能够在用于构建文档的环境中执行,也必须能够在用户可能与此 SciPy 版本一起使用的任何受支持的 numpy/matplotlib 版本中执行。

打包#

最新版本

工具

版本

URL

setuptools

最新

https://pypi.ac.cn/project/setuptools/

wheel

最新

https://pythonwheels.com

multibuild

最新

matthew-brett/multibuild

制作 SciPy 版本分发 包含制作和分发 SciPy 版本的信息。

参考文献#