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中有所增加,现在每年发布一次,因此支持窗口中将始终有 3-4 个 Python 版本。但是,PEP 0602 并没有减少 Python 的支持窗口(18 个月的常规完整错误修复版本和 42 个月的按需仅限源代码版本)。因此,我们不希望我们的用户更快地升级 Python,我们的 42 个月支持窗口将涵盖任何给定 Python 版本的上游支持的相同部分。

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

如果项目在 Python 次版本退出支持窗口后立即发布,则不可避免地会出现支持版本的一些不匹配——但这只应持续到生态系统中的其他项目发布为止。

否则,一旦项目进行次版本或主版本发布,就可以保证所有其他项目的稳定版本在源代码级别上都支持新版本支持的相同 Python 版本集。

如果出现 Python 4 或 NumPy 2,则必须根据社区和项目的最佳利益来审查此策略。

支持表#

日期

Python

NumPy

2020年1月7日

3.6+

1.15+

2020年6月23日

3.7+

1.15+

2020年7月23日

3.7+

1.16+

2021年1月13日

3.7+

1.17+

2021年7月26日

3.7+

1.18+

2021年12月22日

3.7+

1.19+

2021年12月26日

3.8+

1.19+

2022年6月21日

3.8+

1.20+

2023年1月31日

3.8+

1.21+

2023年4月14日

3.9+

1.21+

2023年6月23日

3.9+

1.22+

2024年1月1日

3.9+

1.23+

2024年4月5日

3.10+

1.23+

2024年6月22日

3.10+

1.24+

2024年12月18日

3.10+

1.25+

2025年4月4日

3.11+

1.25+

2026年4月24日

3.12+

1.25+

弃用计划#

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 31, 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 Apr 24, 2026 drop support for Python 3.11 (initially released on Oct 24, 2022)

实现#

我们建议所有项目都将其开发指南中的以下语言纳入其中

本项目支持

  • 项目发布前 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 发行版支持的版本,我们将项目的技术控制权让给了可能与我们有不同动机和关注点的外部组织。

N 个 Python 次要版本#

鉴于 Python 当前的发布节奏,建议的时间(42 个月)大致相当于“最后两个”Python 次要版本。但是,如果 Python 大幅改变其发布节奏,则任何仅基于次要版本数量的规则可能都需要更改才能保持合理。

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

从 X.Y.1 Python 版本开始的时间窗口#

这相当于比从 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
"""

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('============ ====== =====')