工具链路线图#

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 会参考 NEP 29 [1]。从 SciPy 1.3 开始,放弃了对 Python 2.7 的支持。

日期

支持的 Python 版本

2018

Py2.7、Py3.4+(SciPy 1.2.x 是最后一个支持 Python 2.7 的版本)

2019

Py3.5+(但没有删除 Py2.7 特定的代码)

2020

Py3.6+(允许删除 Py2.7 特定的代码)

2021

Py3.7+

2022

Py3.8+

NumPy#

SciPy 依赖于 NumPy,但 SciPy 的版本并不与 NumPy 的版本绑定。SciPy 试图与至少前 4 个版本的 NumPy 兼容。特别是,SciPy 不能依赖于最新 NumPy 的功能,而需要使用所有这 4 个版本中都存在的公共功能 [2]

该表显示了适合每个主要 Python 版本的 NumPy 版本。

SciPy 版本

Python 版本

NumPy 版本

1.2

2.7, >=3.4, <=3.7

>=1.8.2, <= 1.16.x

1.4

>=3.5, <=3.8

>=1.13.3, <= 1.17.3

1.5

>=3.6, <=3.9

>=1.14.5, <= 1.19.3

1.6

>=3.7, <=3.9

>=1.16.5, <= 1.20.x

1.7.0/1

>=3.7, <3.10

>=1.16.5, <1.23.0

1.7.2/3

>=3.7, <3.11

>=1.16.5, <1.23.0

1.8

>=3.8, <3.11

>=1.17.3, <1.24.0

1.9.0/1

>=3.8, <3.12

>=1.18.5, <1.25.0

1.9.2

>=3.8, <3.12

>=1.18.5, <1.26.0

1.10

>=3.8, <3.12

>=1.19.5, <1.26.0

1.11

>=3.9, <3.12

>=1.21.6, <1.27.0

1.12

>=3.9, <3.13

>=1.22.4, <2.0.0

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

编译器#

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

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

如以下更详细的解释,当前的最小编译器版本是

编译器

默认平台(已测试)

辅助平台(未测试)

最小版本

GCC

Linux

AIX、Alpine Linux、OSX

GCC 8.x

LLVM

OSX

Linux、FreeBSD、Windows

LLVM 10.x

MSVC

Windows

Visual Studio 2019 (vc142)

请注意,LLVM 的下限没有强制执行。旧版本应该可以工作 - 只要它们支持核心(非标准库)C++17 -,但在开发过程中,低于 LLVM 12 的版本没有定期测试。如果您在编译过程中遇到问题,请提交问题。

官方构建#

目前,SciPy 轮子正在按以下方式构建

平台

CI 基础镜像 [5] [6] [7]

编译器

注释

Linux x86

ubuntu-22.04

GCC 10.2.1

cibuildwheel

Linux arm

docker-builder-arm64

GCC 11.3.0

cibuildwheel

OSX x86_64

macOS-11

clang-13/gfortran 11.3.0

cibuildwheel

OSX arm64

macos-14

clang-15.0.0/gfortran 13.2.0

cibuildwheel

Windows

windows-2019

GCC 10.3 (rtools)

cibuildwheel

请注意,OSX wheel 额外包含了 gfortran 11.3.0(用于 x86_64)和 gfortran 13.2.0(用于 arm64)。请参阅 tools/wheels/cibw_before_build_macos.sh

C 编译器#

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

过去,在相关平台上,对 C 支持最严格的编译器是 Microsoft Visual C++ 编译器和工具集(统称为 MSVC)[8] [9]。直到 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)[10] 的引入,C 运行时的 ABI 已经稳定,这意味着不再需要使用与底层 CPython 版本相同的编译器版本来编译 SciPy。然而,这种稳定性并非无限期:微软一直在计划[11] 进行一次破坏 ABI 的发布(暂定名为“vNext”),该发布将跨越编译器和 C/C++ 标准库,但目前尚不清楚何时发布。一旦发布,SciPy 将再次被限制在最新的 ABI 兼容的 Visual Studio 版本(目前为 VS 2022),直到所有根据 NEP29 支持的 CPython 版本在 upstream 使用 vNext 兼容的编译器构建完成。

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

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

总而言之,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 具有可选功能 [14](例如原子操作、线程),其中一些功能(VLA 和复杂类型)在 C99 标准中是强制性的。C17(有时称为 C18)可以被视为 C11 的错误修复,因此通常可以完全跳过 C11。

SciPy 在使用更高级的语言功能方面受到可用编译器支持的限制,特别是微软在实现对 C99/C11/C17 的一致性方面进展缓慢,但从 MS Visual Studio 16.8 开始,支持 C11/C17 [15](尽管没有 C11 可选功能)。C99 <complex.h> 对 SciPy 来说尤其有趣;MSVC 对此以及 <stdatomic.h> 的一致性正在这里跟踪 [16] [17]。但是,只要使用特定于 Windows 的类型,仍然可以在 Windows 上使用复杂类型 [18]

因此,使用超出 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(核心语言 + 普遍可用的标准库功能)

?

C++17(包含完整标准库)、C++20、C++23

自放弃对 Python 2.7 的支持以来,C++11 可以普遍使用,而自放弃对 Python 3.6 的支持以来,Visual Studio 版本(之前由于与 CPython 的 ABI 兼容性而一直停留在 14.0)已经足够新,可以支持 C++17。

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

在 2021 年底(随着 manylinux1 滚轮的最终移除),GCC 的最低要求升级到了 6.3,它完全支持 C++14 [20]。这对应于相关 manylinux 版本中最低的 GCC 版本,尽管这仍然考虑了基于 Debian 的“异常值” manylinux_2_24,它与基于 RHEL 的 CentOS 的先前 manylinux 镜像不同,这些镜像可以从“RHEL Dev Toolset”中受益于 ABI 兼容的 GCC 后移植,而它却停留在 GCC 6.3。该镜像未能成功推出,原因至少是这些过时的编译器 [21],并在 2022 年年中达到其生命周期结束 (EOL) [22]。由于不同的原因,manylinux2010 也在同一时间左右达到其 EOL [23]

剩余的镜像 manylinux2014manylinux_2_28 目前分别支持 GCC 10 和 11。后者将继续接收更新,因为新的 GCC 版本将作为后移植提供,但前者可能不会改变,因为 CentOS 项目不再对发布 GCC 11 的 aarch64 后移植做出响应 [24]

这使得所有主要平台及其编译器都拥有相对较新的版本。但是,SciPy 历史上也努力支持不太常见的平台,即使不是使用二进制制品(即滚轮),至少也要保持从源代码编译的能力,其中包括 AIX、Alpine Linux 和 FreeBSD。

对于 AIX 7.1 和 7.2,默认编译器是 GCC 8(AIX 6.1 在 2017 年达到其 EOL),但 GCC 10 可以安装(并行) [25]。目前支持的最古老的 Alpine Linux 版本是 3.12 [26],并且已经附带了 GCC 10。对于 FreeBSD,目前支持的最古老的 12.x 版本 [27] 附带了 LLVM 10(GCC 10 可作为 freebsd-port 获得 [28])。

最后,还有一个问题是,哪些机器被广泛用于需要从源代码编译 SciPy 的人(例如 SciPy 开发人员,或出于性能原因想要自己编译的人)。最古老的相关发行版(没有 RHEL 风格的回溯移植)是 Ubuntu 18.04 LTS(它有 GCC 7,但也回溯移植了 GCC 8;Ubuntu 20.04 LTS 有 GCC 9)和 Debian Buster(有 GCC 8;Bullseye 有 GCC 10)。这是确定编译器支持下限的最弱限制(可以预期高级用户和开发人员会将他们的系统至少保持在一定程度上更新,或在可用时使用回溯移植),随着旧发行版的使用数量减少,它逐渐变得不那么重要。

所有当前支持最低的编译器版本(GCC 8、LLVM 12、VS2019 with vc142)都完全支持 C++17 *核心语言*,因此可以无条件使用。但是,截至 2022 年年中,对所有编译器 [20] 的 C++17 标准库的完整支持尚未完成,特别是 LLVM。因此,在 SciPy 中使用某个 stdlib 功能之前,有必要检查它是否受所有编译器支持。对 C++20 和 C++23 的编译器支持仍在积极开发中 [20]

Fortran 编译器#

一般来说,任何维护良好的编译器都可能适合,并且可以用来构建 SciPy。

工具

版本

gfortran

>= 4.8.0

ifort

最新版本

flang

最新版本

Cython & Pythran#

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

OpenMP 支持#

由于各种原因 [29],SciPy 无法与内置的 OpenMP 支持一起分发。当使用可选的 Pythran 支持时,可以在从源代码构建时生成启用 OpenMP 的并行代码。

其他库#

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

最低版本

LAPACK

3.7.1

BLAS

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

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

版本

网址

mpmath

最新

http://mpmath.org/

scikit-umfpack

最新

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

pooch

最新

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

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

工具

版本

网址

pydata/sparse

最新

pydata/sparse

测试和基准测试#

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

工具

版本

网址

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.12.0

注意

开发者注意:numpymatplotlib 的版本要求会影响 Python 文档字符串中的示例。示例必须能够在用于构建文档的环境中执行,以及用户可能与该 SciPy 版本一起使用的任何支持的 numpy/matplotlib 版本中执行。

打包#

最新版本的

工具

版本

网址

setuptools

最新

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

wheel

最新

https://pythonwheels.com

multibuild

最新

matthew-brett/multibuild

发布 SciPy 版本分发 包含有关发布和分发 SciPy 版本的信息。

参考资料#