工具链路线图#

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

构建 SciPy#

Python 版本#

SciPy 兼容多个版本的 Python。在停止支持旧版本 Python 时,SciPy 参考 [NEP29] 的指导。通常,对最旧 Python 版本的支持会在其原始发布 42 个月后停止。随着 PEP 602 的采纳,这主要发生在 4 月,并在 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 尝试与至少前 4 个版本的 NumPy 保持兼容。特别地,SciPy 不能仅依赖最新版 NumPy 的特性,而需要使用这 4 个 NumPy 发行版 中通用的功能进行编写。

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

该表显示了适用于每个 SciPy 次要版本的 NumPy 和 Python 版本。请注意,并非特定 SciPy 次要版本的所有修订版(patch versions)都支持所有列出的 Python 版本。只有每个次要版本中的最新修订版才保证支持所有列出的 Python 版本。

SciPy 版本

Python 版本

NumPy 版本

1.16

>=3.11, <3.14

>=1.25.2, <2.6.0

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 版本。只要支持核心(非标准库)C++17,比 SciPy CI 中使用的更早的版本应该也能工作。如果您在编译过程中遇到问题,请提交 Issue。

官方构建#

目前,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 另外为 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 版本相同的编译器版本。这种稳定性并非无限期的:微软一直计划发布一个破坏 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 版本及镜像中的 GCC 版本 [MANY]

2021 年底(随着 manylinux1 wheel 的最终移除),GCC 的最低要求移至 6.3,该版本具有完整的 C++14 支持 [CPP]。这对应于相关 manylinux 版本中存在的最低 GCC 版本,尽管当时仍考虑了基于 Debian 的“例外” manylinux_2_24。与基于 RHEL 衍生版 CentOS、可受益于“RHEL Dev Toolset”中 ABI 兼容的 GCC 反向移植的先前 manylinux 镜像不同,manylinux_2_24 困于 GCC 6.3。该镜像未能流行很大程度上是由于这些 过时的编译器,并于 2022 年年中达到 EOL。由于不同原因,manylinux2010 也在 同一时间 达到了 EOL。

剩余的镜像 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;同样,还有基于 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 中使用某个标准库特性之前,有必要检查它是否被所有编译器支持。

C++20 的支持稳定速度非常缓慢,除了模块(modules)、协程(coroutines)和几个尚未被普遍支持的标准库特性外。考虑到 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 发行版的信息。

参考文献#