NEP 29 — 建议将 Python 和 NumPy 版本支持作为一项社区政策标准#

作者:

Thomas A Caswell <tcaswell@gmail.com>, Andreas Mueller, Brian Granger, Madicken Munk, Ralf Gommers, Matt Haberland <mhaberla@calpoly.edu>, Matthias Bussonnier <bussonniermatthias@gmail.com>, Stefan van der Walt <stefanv@berkeley.edu>

状态:

最终

类型:

信息性

创建日期:

2019-07-13

决议:

https://mail.python.org/pipermail/numpy-discussion/2019-October/080128.html

注意

此 NEP 已被科学 Python 生态系统协调指南 SPEC 0 — 最低支持版本 取代。

摘要#

本 NEP 建议科学 Python 生态系统中的所有项目采纳一项基于“时间窗口”的共同政策,以支持 Python 和 NumPy 版本。将项目对最低 Python 和 NumPy 版本的支持标准化,将改善下游项目规划。

这是一个不同寻常的 NEP,因为它提出了社区范围内的政策建议,而不是对 NumPy 本身进行更改。由于目前没有一个统一的 SPEEP(科学 Python 生态系统改进提案)平台,并且考虑到 NumPy 在生态系统中的核心作用,因此 NEP 提供了一个可见的场所来记录这项拟议政策。

本 NEP 由 Matplotlib、scikit-learn、IPython、Jupyter、yt、SciPy、NumPy 和 scikit-image 的维护者共同提出。

详细描述#

为本 NEP 之目的,我们假定语义化版本控制并定义

主版本

更改第一个数字的版本(例如 X.0.0)

次版本

更改第二个数字的版本(例如 1.Y.0)

补丁版本

更改第三个数字的版本(例如 1.1.Z)

当项目发布新的主版本或次版本时,我们建议它们至少支持在**预计发布日期前** 42 个月内引入和发布的所有 Python 次版本(且至少包含两个 Python 次版本),以及在**预计发布日期前** 24 个月内发布的所有 NumPy 次版本(且至少包含三个 NumPy 次版本)。

请考虑以下时间线

     Jan 16      Jan 17      Jan 18      Jan 19      Jan 20
     |           |           |           |           |
+++++|+++++++++++|+++++++++++|+++++++++++|+++++++++++|++++++++++++
 |              |                  |               |
 py 3.5.0       py 3.6.0           py 3.7.0        py 3.8.0
|-----------------------------------------> Feb19
          |-----------------------------------------> Dec19
                    |-----------------------------------------> Nov20

它显示了 Python 的 42 个月支持窗口。在 2019 年 2 月发布主版本或次版本的项目应支持 Python 3.5 及更高版本,在 2019 年 12 月发布主版本或次版本的项目应支持 Python 3.6 及更高版本,在 2020 年 11 月发布主版本或次版本的项目应支持 Python 3.7 及更高版本。

本 NEP 起草时,Python 的发布周期为 18 个月,因此 42 个月的窗口期确保了在该窗口内始终至少有两个 Python 次版本。该窗口期在 Python 预期的两个发布间隔基础上又延长了 6 个月,以应对其发布计划中的小幅波动/延迟。

Python 的发布周期在 PEP 0602 中有所增加,现在每 12 个月发布一次,因此在任何时候的支持窗口内都会有 3-4 个 Python 版本。然而,PEP 0602 并未缩短 Python 的支持窗口(18 个月的常规完整错误修复版本和 42 个月的按需仅源代码版本)。因此,我们不期望用户更快地升级 Python,我们的 42 个月支持窗口将覆盖任何给定 Python 版本的上游支持的相同部分。

由于 Python 次版本支持仅基于历史发布日期、42 个月的时间窗口以及计划的项目发布日期,因此可以高度自信地预测项目何时能够放弃对任何给定 Python 次版本的支持。这反过来可以节省数月不必要的维护负担。

如果一个项目在某个 Python 次版本超出支持窗口后立即发布,那么在支持版本上不可避免地会出现一些不匹配——但这种情况只应持续到生态系统中其他项目发布新版本为止。

否则,一旦项目发布次版本或主版本,则保证生态系统中所有其他项目,在源代码层面,将支持与新版本相同的 Python 版本集合的稳定发布。

如果出现 Python 4 或 NumPy 2,则需要根据社区和项目的最佳利益重新审查此政策。

支持表#

日期

Python

NumPy

Jan 07, 2020

3.6+

1.15+

Jun 23, 2020

3.7+

1.15+

Jul 23, 2020

3.7+

1.16+

Jan 13, 2021

3.7+

1.17+

Jul 26, 2021

3.7+

1.18+

Dec 22, 2021

3.7+

1.19+

Dec 26, 2021

3.8+

1.19+

Jun 21, 2022

3.8+

1.20+

Jan 31, 2023

3.8+

1.21+

Apr 14, 2023

3.9+

1.21+

Jun 23, 2023

3.9+

1.22+

Jan 01, 2024

3.9+

1.23+

Apr 05, 2024

3.10+

1.23+

Jun 22, 2024

3.10+

1.24+

Dec 18, 2024

3.10+

1.25+

Apr 04, 2025

3.11+

1.25+

Jun 17, 2025

3.11+

1.26+

Sep 16, 2025

3.11+

2.0+

Apr 24, 2026

3.12+

2.0+

Jun 16, 2026

3.12+

2.1+

Aug 19, 2026

3.12+

2.2+

Dec 09, 2026

3.12+

2.3+

Apr 02, 2027

3.13+

2.3+

Apr 07, 2028

3.14+

2.3+

淘汰计划#

On next release, drop support for Python 3.5 (initially released on Sep 13, 2015)
On Jan 07, 2020 drop support for NumPy 1.14 (initially released on Jan 06, 2018)
On Jun 23, 2020 drop support for Python 3.6 (initially released on Dec 23, 2016)
On Jul 23, 2020 drop support for NumPy 1.15 (initially released on Jul 23, 2018)
On Jan 13, 2021 drop support for NumPy 1.16 (initially released on Jan 13, 2019)
On Jul 26, 2021 drop support for NumPy 1.17 (initially released on Jul 26, 2019)
On Dec 22, 2021 drop support for NumPy 1.18 (initially released on Dec 22, 2019)
On Dec 26, 2021 drop support for Python 3.7 (initially released on Jun 27, 2018)
On Jun 21, 2022 drop support for NumPy 1.19 (initially released on Jun 20, 2020)
On Jan 31, 2023 drop support for NumPy 1.20 (initially released on Jan 30, 2021)
On Apr 14, 2023 drop support for Python 3.8 (initially released on Oct 14, 2019)
On Jun 23, 2023 drop support for NumPy 1.21 (initially released on Jun 22, 2021)
On Jan 01, 2024 drop support for NumPy 1.22 (initially released on Dec 31, 2021)
On Apr 05, 2024 drop support for Python 3.9 (initially released on Oct 05, 2020)
On Jun 22, 2024 drop support for NumPy 1.23 (initially released on Jun 22, 2022)
On Dec 18, 2024 drop support for NumPy 1.24 (initially released on Dec 18, 2022)
On Apr 04, 2025 drop support for Python 3.10 (initially released on Oct 04, 2021)
On Jun 17, 2025 drop support for NumPy 1.25 (initially released on Jun 17, 2023)
On Sep 16, 2025 drop support for NumPy 1.26 (initially released on Sep 16, 2023)
On Apr 24, 2026 drop support for Python 3.11 (initially released on Oct 24, 2022)
On Jun 16, 2026 drop support for NumPy 2.0 (initially released on Jun 15, 2024)
On Aug 19, 2026 drop support for NumPy 2.1 (initially released on Aug 18, 2024)
On Dec 09, 2026 drop support for NumPy 2.2 (initially released on Dec 08, 2024)
On Apr 02, 2027 drop support for Python 3.12 (initially released on Oct 02, 2023)
On Apr 07, 2028 drop support for Python 3.13 (initially released on Oct 07, 2024)

实施#

我们建议所有项目在其开发指南中采纳以下措辞

本项目支持

  • 项目发布前 42 个月内发布的所有 Python 次版本,且至少包含两个最新的次版本。

  • 项目发布前 24 个月内发布的所有 numpy 次版本,且至少包含最新的三个次版本。

setup.py 中,python_requires 变量应设置为支持的最低 Python 版本。所有受支持的 Python 次版本都应包含在测试矩阵中,并为发布构建二进制产物。

最低 Python 和 NumPy 版本支持应在每次主版本和次版本发布时向上调整,但补丁版本发布时绝不调整。

向后兼容性#

无向后兼容性问题。

替代方案#

临时版本支持#

项目可以在每次发布时评估是否提高 Python 支持的最低版本。一个主要缺点是,临时方法使得下游用户难以预测未来的最低版本。由于没有客观的阈值来确定何时应放弃最低版本,因此这些版本支持讨论很容易演变为“自行车棚效应”和争执。

所有 CPython 支持的版本#

CPython 支持的 Python 版本列在《Python 开发者指南》和 Python PEP 中。支持这些版本是一种非常清晰和保守的方法。然而,这意味着语言中引入新功能与项目能够使用该功能之间存在四年的滞后。此外,对于带有编译扩展的项目,这需要为每个版本构建许多二进制产物。

对于 NumPy,许多项目对后续 NumPy 版本中修复的错误进行变通处理。积极提高 NumPy 的最低版本可以使下游包减少特定于版本的补丁。

Linux 发行版上的默认版本#

政策可以定为支持最新 Ubuntu LTS 或 CentOS/RHEL 版本中默认附带的 Python 版本。然而,我们仍然需要在社区中标准化应遵循哪个发行版。

通过遵循主流 Linux 发行版所支持的版本,我们正在将项目的技术控制权交给可能与我们有不同动机和关注点的外部组织。

Python 的 N 个次版本#

鉴于 Python 当前的发布周期,提议的时间(42 个月)大致相当于“最近两个”Python 次版本。然而,如果 Python 大幅改变其发布周期,任何仅基于次版本数量的规则可能需要更改以保持合理性。

基于 Python 发布数量的政策存在一个更根本的问题,即难以预测何时会放弃对给定 Python 次版本的支持,因为这需要正确预测 Python 未来 3-4 年的发布计划。相比之下,基于时间的规则仅取决于过去的事件和支持窗口的长度。

从 Python X.Y.1 版本发布算起的时间窗口#

这相当于从 X.Y.0 版本发布算起延长了几个月的支持窗口。这是因为 X.Y.1 错误修复版本通常在 X.Y.0 版本发布后几个月发布,因此从 X.Y.1 算起的 N 个月窗口大致相当于从 X.Y.0 算起的 N+3 个月。

X.Y.0 版本自然是一个特殊版本。如果我们将窗口锚定在 X.Y.1,那么就会出现为什么不选择 X.Y.M 的讨论?

讨论#

参考文献和脚注#

生成支持和淘汰计划表的代码

from datetime import datetime, timedelta

data = """Jan 15, 2017: NumPy 1.12
Sep 13, 2015: Python 3.5
Dec 23, 2016: Python 3.6
Jun 27, 2018: Python 3.7
Jun 07, 2017: NumPy 1.13
Jan 06, 2018: NumPy 1.14
Jul 23, 2018: NumPy 1.15
Jan 13, 2019: NumPy 1.16
Jul 26, 2019: NumPy 1.17
Oct 14, 2019: Python 3.8
Dec 22, 2019: NumPy 1.18
Jun 20, 2020: NumPy 1.19
Oct 05, 2020: Python 3.9
Jan 30, 2021: NumPy 1.20
Jun 22, 2021: NumPy 1.21
Oct 04, 2021: Python 3.10
Dec 31, 2021: NumPy 1.22
Jun 22, 2022: NumPy 1.23
Oct 24, 2022: Python 3.11
Dec 18, 2022: NumPy 1.24
Jun 17, 2023: NumPy 1.25
Sep 16, 2023: NumPy 1.26
Oct 2, 2023: Python 3.12
Jun 15, 2024: NumPy 2.0
Aug 18, 2024: NumPy 2.1
Oct 7, 2024: Python 3.13
Dec 8, 2024: NumPy 2.2
"""

releases = []

plus42 = timedelta(days=int(365*3.5 + 1))
plus24 = timedelta(days=int(365*2 + 1))

for line in data.splitlines():
    date, project_version = line.split(':')
    project, version = project_version.strip().split(' ')
    release = datetime.strptime(date, '%b %d, %Y')
    if project.lower() == 'numpy':
        drop = release + plus24
    else:
        drop = release + plus42
    releases.append((drop, project, version, release))

releases = sorted(releases, key=lambda x: x[0])


py_major,py_minor = sorted([int(x) for x in r[2].split('.')] for r in releases if r[1] == 'Python')[-1]
minpy = f"{py_major}.{py_minor+1}+"

num_major,num_minor = sorted([int(x) for x in r[2].split('.')] for r in releases if r[1] == 'NumPy')[-1]
minnum = f"{num_major}.{num_minor+1}+"

toprint_drop_dates = ['']
toprint_support_table = []
for d, p, v, r in releases[::-1]:
    df = d.strftime('%b %d, %Y')
    toprint_drop_dates.append(
        f'On {df} drop support for {p} {v} '
        f'(initially released on {r.strftime("%b %d, %Y")})')
    toprint_support_table.append(f'{df} {minpy:<6} {minnum:<5}')
    if p.lower() == 'numpy':
        minnum = v+'+'
    else:
        minpy = v+'+'
print("On next release, drop support for Python 3.5 (initially released on Sep 13, 2015)")
for e in toprint_drop_dates[-4::-1]:
    print(e)

print('============ ====== =====')
print('Date         Python NumPy')
print('------------ ------ -----')
for e in toprint_support_table[-4::-1]:
    print(e)
print('============ ====== =====')