工具链路线图#

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 版本

2026

Py3.12+

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 次要版本的所有补丁版本都支持列出的所有 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 版本开始的可选依赖项)。

为了在大量平台和设置上保持兼容,特别是无法使用官方二进制轮(wheels)或 Anaconda、conda-forge 等分发渠道时,SciPy 尽量在尚未达到官方生命周期终止(EOL)的平台上保持与旧编译器的兼容性。

如下所述,当前最低编译器版本为

编译器

默认平台(已测试)

辅助平台(未测试)

最低版本

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 中使用的版本更旧的版本应该也可以工作。如果在编译过程中遇到问题,请提交问题。

官方构建#

目前,SciPy 二进制轮的构建方式如下

平台

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-15-intel

Apple clang 13.1.6/gfortran 15.2.0

cibuildwheel

OSX x86_64 (Accelerate)

macos-15-intel

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-2025

GCC 15.2.0 (rtools)

cibuildwheel

请注意,OSX 轮还额外捆绑了 libgfortran dylib。

C 编译器#

SciPy 与大多数现代 C 编译器兼容(特别是 clang)。如今,所有相关编译器对最新的 C 语言标准都有相当好的支持,尽管这与过去的情况大不相同。以下段落主要讨论这些限制的演变;不关心历史背景的读者可以直接跳至末尾的表格。

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

过去,相关平台上在 C 支持方面限制最严格的编译器是微软 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 的编译器构建完成为止。

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

这是因为尽管工具集版本之间保持 ABI 兼容性(直到 vNext),但所有链接操作都必须使用至少与构建任何相关工件时一样新的工具集,这意味着工具集版本提升往往是“传染性”的,即:要求所有消费库也必须提升其工具集(以及编译器)版本。这对 NumPy 来说比 SciPy 的问题更大,因为后者的 C API 很小,且被编译链接的项目远少于 NumPy。此外,使用更新的工具集意味着使用编译 C++ 代码库(如 SciPy)的用户可能还需要更新的微软 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 上使用复数类型。

因此,使用超出 C90 的 C 功能仅在 Windows 上有支持时才可行;然而,截至 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 轮的最终移除),GCC 的最低要求移至 6.3,该版本具有完整的 C++14 支持 [CPP]。这对应于相关 manylinux 版本中存在的最低 GCC 版本,尽管这仍然考虑到了基于 Debian 的“离群值” manylinux_2_24,它——与之前基于 RHEL 衍生版 CentOS、可以受益于“RHEL Dev Toolset”中 ABI 兼容 GCC 向后移植的 manylinux 镜像不同——被困在 GCC 6.3。由于这些 过时的编译器,该镜像未能流行起来,并在 2022 年年中达到了生命周期终点(EOL)。由于不同的原因,manylinux2010 也在大约 相同时间 达到了 EOL。

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

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

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

对于 AIX 7.2 和 7.3,默认编译器是 GCC 10(AIX 7.1 已于 2023 年 EOL),但可以 并排 安装 GCC 11/12,同样还有基于 LLVM 17 的 Open XL 用于 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, VS2019 带 vc142)都完全支持 C++17 核心语言,因此可以无条件使用。然而,截至 2024 年年中,C++17 标准库的完整性尚未在所有编译器中完成 [CPP],特别是 LLVM。因此,在 SciPy 中使用给定的 stdlib 特性之前,必须检查它是否得到所有编译器的支持。

C++20 的支持正在非常缓慢地稳定,甚至不包括模块、协程和几个尚未被普遍支持的 stdlib 特性。鉴于 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 文档字符串中的示例有影响。示例必须能够在构建文档的环境中以及用户可能与此 SciPy 版本一起使用的任何受支持的 numpy/matplotlib 版本中执行。

打包#

较新版本的

工具

版本

URL

setuptools

近期

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

wheel

近期

https://pythonwheels.com

multibuild

近期

matthew-brett/multibuild

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

参考文献#