工具链路线图#

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 中使用的工具产生一些影响。它还对文档中使用的示例(例如,函数的文档字符串)产生影响,因为这些示例只能使用所有受支持配置中存在的功能。

构建 SciPy#

Python 版本#

SciPy 与多个 Python 版本兼容。当停止对旧 Python 版本的支持时,SciPy 会参考 [NEP29]。通常,对最旧的 Python 版本的支持会在原始版本发布 42 个月后停止。在接受 PEP 602 后,这种情况大多发生在 4 月,并在 SciPy 的年中版本中被采用。

Python 版本支持随时间推移

从 SciPy 1.3 开始停止对 Python 2.7 的支持。

日期

支持的 Python 版本

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 尝试与至少 4 个以前的 NumPy 版本兼容。特别是,SciPy 不能仅仅依赖于最新 NumPy 的功能,而是需要使用所有这 4 个 NumPy 版本 中通用的功能来编写。

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

该表显示了适合每个主要 Python 版本的 NumPy 版本。此表不区分 SciPy 修补程序版本(例如,当发布新的 Python 版本时,SciPy 通常会发布兼容的修补程序版本)。

SciPy 版本

Python 版本

NumPy 版本

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 版本开始是可选的依赖项)。

为了保持与大量平台和设置的兼容性,尤其是在无法使用官方 wheels(或其他发行渠道,如 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 版本。只要它们支持核心(非 stdlib)C++17,则使用低于 SciPy CI 中使用的版本应该可以工作。如果在编译过程中遇到问题,请提交问题。

官方构建#

目前,SciPy wheels 的构建方式如下

平台

CI Base 镜像

编译器

注释

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 wheels 另外为 x86_64 供应商 gfortran 11.3.0,为 arm64 供应商 gfortran 12.1.0。请参阅 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 版本相同的编译器版本的限制。但是,这种稳定性并非无限期:Microsoft 一直在计划发布一个 ABI 破坏版本(跨编译器 resp. 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 在使用更高级的语言特性方面受到可用编译器支持的限制,特别是 Microsoft 花了很长时间才实现对 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(核心语言 + 通用的 stdlib 特性)

?

C++17(完整 stdlib),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 wheels),GCC 的最低要求提高到 6.3,它具有完整的 C++14 支持[CPP]。这与相关 manylinux 版本中存在的最低 GCC 版本相对应,但这仍然考虑了基于 Debian 的“异常值”manylinux_2_24,与之前基于 RHEL 衍生 CentOS 的 manylinux 镜像不同,后者可以从“RHEL Dev Toolset”中的 ABI 兼容 GCC 向后移植中受益,而是停留在 GCC 6.3。该镜像未能取得成功,尤其是由于那些过时的编译器,并且在 2022 年年中达到了 EOL。由于不同的原因,manylinux2010也在大约同一时间达到了 EOL。

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

这使得所有主要平台及其编译器都具有相对较新的版本。但是,SciPy 在历史上也一直努力支持不太常见的平台,即使没有二进制工件(即 wheels),至少也要保持从源代码可编译的状态,这包括例如 AIX、Alpine Linux 和 FreeBSD。

平台支持和对编译器的其他限制

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

当前支持的最旧的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 中使用给定的 stdlib 功能之前,必须检查所有编译器是否都支持该功能。

即使不考虑模块、协程和几个尚未普遍支持的 stdlib 特性,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.13.1

jupyterlite-pyodide-kernel

任何最近可用的版本。>= 0.1.0

注意

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

打包#

最近的版本

工具

版本

URL

setuptools

最新

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

wheel

最新

https://pythonwheels.com

multibuild

最新

matthew-brett/multibuild

制作 SciPy 发行版分发 包含有关制作和分发 SciPy 发行版的信息。

参考文献#