Following system colour scheme - Python 增强提案 Selected dark colour scheme - Python 增强提案 Selected light colour scheme - Python 增强提案

Python 增强提案

PEP 598 – 引入增量功能发布

作者:
Alyssa Coghlan <ncoghlan at gmail.com>
讨论至:
Discourse 帖子
状态:
已撤回
类型:
信息性
创建日期:
2019 年 6 月 15 日
Python 版本:
3.9

目录

摘要

PEP 602 提议通过将 CPython 功能发布的频率从每 18-24 个月增加到每 9-12 个月,来减少 Python 标准库和 CPython 参考解释器的功能交付延迟。

本 PEP 提议改为减少新基线功能发布(及其相关的文件系统布局更改、字节码格式更改和 C ABI 兼容性中断)的频率,使其每两年发布一次(2020、2022、2024 等),但将此更改与一项新政策和方法相结合,允许在新发布系列的点发布集合中引入向后兼容的功能。

PEP 撤回

本 PEP 已被撤销,以支持 PEP 605 中提出的滚动 Beta 发布流提案。

然而,本 PEP 中提出的担忧可能会适用于任何其他“长期支持分支”提案,这些提案允许功能回溯以改善支持此类发布的开发人员体验(例如 [3] 中的 EL Python 草案),因此此处提出的想法可能会为这些提案提供有用的设计建议。

总结

提出的通过更频繁地进行当前 CPython 发布兼容性管理流程,但每次的频率更高,这存在显著的实际弊端,因为 CPython 功能发布带有一些期望(最重要的是,5 年的维护生命周期、与前一个功能发布并行安装的支持,以及可能破坏 CPython 特定 ABI 的更改,需要重新编译所有扩展模块),这意味着当前形式的更频繁的功能发布有可能显著增加维护所有积极支持的 CPython 版本上第三方 Python 库和应用程序的负担。

此外,也可以争辩说,这种方法是否能在实践中明显减少大多数最终用户的典型功能交付延迟,因为新功能发布的采用周期通常以月或年为单位,所以更频繁的发布可能只会导致最终用户更新到每 3 个或 4 个功能发布,而不是每 2 个或 3 个功能发布(如今天经常发生的那样)。

本 PEP 提出了一项竞争性提案,该提案建议将文件系统布局和 CPython ABI 发生变化的并行可安装功能发布的频率放缓,使其达到固定的 24 个月周期,但通过引入构建兼容的增量功能发布的概念来弥补这一点,然后将给定功能发布系列的总功能冻结期从最初的基线 X.Y.0 版本推迟到大约 12 个月后发生的后续 X.Y.Z 功能完整发布。

`sys.version_info` 结构中的一个新 `feature_complete` 属性将提供一个程序化指标,指示一个发布系列是否仍然开放以进行进一步的增量功能发布。 Python 的其他实现也可以清除此标志,以表明它们对标称 Python 版本的支持可能仍在进行中。

为了兼容性测试目的,并为了在混合版本环境中保持 pickle 兼容性,一个新的 `sys.feature_limit` 属性(以及相应的 CPython CLI 参数 `--feature-limit X.Y.Z` 和环境变量 `PYTHONFEATURELIMIT`)将提供一种方法来限制增量功能发布中添加的功能的运行时可用性。

现有周期和新周期将在其功能冻结发布日期上同步,因此完整的 Python 3.9.x 功能冻结将在 2021 年 10 月发生,即 Python 3.8.0 功能发布后 24 个月,而最初的 Python 3.9.0 发布将在 2020 年 10 月进行。

示例未来发布计划

根据此提案,Python 3.9.0a1 将于 2019 年 11 月发布,紧随 2019 年 10 月发布的 Python 3.8.0 功能完整版之后。

然后,3.9.0b1 发布将在 6 个月后的 2020 年 5 月进行,而 3.9.0 本身将于 2020 年 10 月发布。

假设 3.9.x 的微发布每季度发生一次,那么整体发布时间线将如下所示:

  • 2019-11:3.9.0a1
  • … 由发布经理决定的其他 alpha 版本
  • 2020-05:3.9.0b1
  • … 由发布经理决定的其他 beta 版本
  • 2020-08:3.9.0bX(锁定 ABI 兼容性的最终 beta 版本)
  • 2020-09:3.9.0rc1
  • … 由发布经理决定的其他发布候选版本
  • 2020-10:3.9.0(BFR - 基线功能发布)
  • 2021-01:3.9.1(IFR - 增量功能发布)
  • 2021-04:3.9.2(IFR)
  • 2021-07:3.9.3(IFR)
  • 2021-10:3.9.4(功能完整发布)
  • 2022-01: 3.9.5
  • 2022-04: 3.9.6
  • 2022-07: 3.9.7
  • 2022-10:3.9.8(最终常规维护发布)
  • … 按需进行其他仅安全修复的发布
  • 2025-10:3.9.x 分支关闭

功能完整发布编号通常会像今天一样,不带任何限定符(即 X.Y.Z 发布),而基线和增量功能发布预计会附加一个限定符,表明它们不是传统的 CPython 发布(例如 `3.9.0 (BFR)`、`3.9.1 (IFR)` 等)。

Python 3.10 发布系列将在第一个 Python 3.9 功能完整发布后的一个月开始发布,并与 Python 3.9 维护发布的最后 12 个月并行。

  • 2021-11:3.10.0a1
  • … 由发布经理决定的其他 alpha 版本
  • 2022-05:3.10.0b1
  • … 由发布经理决定的其他 beta 版本
  • 2022-08:3.10.0bX(锁定 ABI 兼容性的最终 beta 版本)
  • 2022-09:3.10.0rc1
  • … 由发布经理决定的其他发布候选版本
  • 2022-10:3.10.0(BFR)
  • 2023-01:3.10.1(IFR)
  • 2023-04:3.10.2(IFR)
  • 2023-07:3.10.3(IFR)
  • 2023-10: 3.10.4
  • 2024-01: 3.10.5
  • 2024-04: 3.10.6
  • 2024-07: 3.10.7
  • 2024-10:3.10.8(最终常规维护发布)
  • … 按需进行其他仅安全修复的发布
  • 2027-10:3.10.x 分支关闭

在此模型中,始终有两个或三个活动分支

  • 2019-04 -> 2019-10:3.9.0 预 Alpha 版、3.8.0 预发布版、3.7.x 维护版
  • 2019-10 -> 2020-05:3.9.0 预 Beta 版、3.8.x 维护版
  • 2020-05 -> 2020-10:3.10.0 预 Alpha 版、3.9.0 预发布版、3.8.x 维护版
  • 2020-10 -> 2021-10:3.10.0 预 Alpha 版、3.9.x 功能发布、3.8.x 维护版
  • 2021-10 -> 2022-05:3.10.0 预 Beta 版、3.9.x 维护版
  • 2022-05 -> 2022-10:3.11.0 预 Alpha 版、3.10.0 预发布版、3.9.x 维护版
  • 2022-10 -> 2023-10:3.11.0 预 Alpha 版、3.10.x 功能发布、3.9.x 维护版
  • 2023-10 -> 2024-05:3.11.0 预 Beta 版、3.10.x 维护版
  • 2024-05 -> 2024-10:3.12.0 预 Alpha 版、3.11.0 预发布版、3.10.x 维护版
  • … 等等

(预 Alpha 版和预 Beta 版开发发生在主 git 分支上,所有其他开发发生在特定发布分支上,通常会将更改从主 git 分支回溯到旧版本)

待办:这真的需要一个图表来帮助解释,一旦我有了要添加的图片,我会添加它。

这与现状非常相似,但节奏更一致,在基线功能发布年份(2020、2022 等)之间交替进行,这些年份侧重于新基线功能发布的 Alpha 和 Beta 周期(同时继续为前一个功能发布系列发布维护版本),以及功能完整发布年份(2021、2023 等),这些年份侧重于对当前功能发布系列进行较小的改进(同时为来年规划下一个功能发布系列)。

提案

排除 Alpha 和 Beta 版本,CPython 目前有 3 种不同类型的发布增量

  • 功能发布(即 X.Y.0 发布)
  • 维护发布(X.Y.0 发布后约 2 年内的 X.Y.Z 发布)
  • 仅源代码安全发布(后续的 X.Y.Z 发布)

功能冻结发生在 X.Y.0b1 发布时。构建兼容性冻结现在发生在最后一个 Beta 版本发布时(为项目在第一个发布候选版本之前将 wheel 归档上传到 PyPI 提供了时间)。

然后,这将创建一个发布系列生命周期中的以下时期

  • 预 Beta 版(发布系列是 CPython 开发分支)
  • Beta 版(发布进入维护模式,ABI 兼容性基本锁定)
  • 维护(ABI 锁定,仅接受错误修复和文档增强)
  • 仅安全修复(不再发布二进制文件,仅接受安全修复)
  • 生命周期结束(不再发布任何类型的版本)

本 PEP 中的提案是,将“功能发布”类别分为三种不同类型的功能发布

  • 基线功能发布(X.Y.0 发布)
  • 增量功能发布(基线功能发布和相应的功能完整发布之间发布的任何 X.Y.Z 发布)
  • 功能完整发布(X.Y.0 发布后约 1 年的特定 X.Y.Z 发布)
  • 维护发布(功能完整发布后约 1 年内的 X.Y.Z 发布)
  • 仅源代码安全发布(后续的 `X.Y.Z` 发布)

这将引入发布系列生命周期中的一个新的“功能发布”阶段

  • 预 Beta 版(发布系列是 CPython 开发分支)
  • Beta 版(发布进入功能添加模式,ABI 兼容性尚未锁定)
  • 功能发布(ABI 锁定,接受向后兼容的 API 添加)
  • 维护(ABI 锁定,仅接受错误修复和文档增强)
  • 仅安全修复(不再发布二进制文件,仅接受安全修复)
  • 生命周期结束(不再发布任何类型的版本)

预发布 Beta 阶段将放宽,使用增量功能发布策略进行更改,而不是更严格的维护发布策略。

出于治理目的,基线功能发布是唯一符合 PEP 13 意义上的“功能发布”的发布(增量功能发布不计入)。

基线功能发布和功能发布系列

基线功能发布本质上就是现有的功能发布,只是给它们起了个新名字,以便与新的增量功能发布区分开来,并表明与之前的版本不同,它们在发布时不再被视为功能完整。

基线功能发布将继续定义一个新的功能发布系列,锁定该系列其余部分的以下语言、构建和安装兼容性约束

  • Python 语言语法
  • `ast` 模块 AST 格式
  • CPython 解释器操作码格式
  • `pyc` 文件魔术数字和文件名兼容性标签
  • 扩展模块文件名兼容性标签
  • wheel 归档兼容性标签
  • 默认包和模块导入目录
  • 默认安装文件名和目录

基线功能发布也将继续是唯一可以引入以下内容的版本

  • 新的弃用、待定弃用和其他警告
  • 现有的待定弃用可以转换为完全弃用
  • 现有警告可以转换为错误
  • 其他需要“迁移到 Python X.Y”条目的更改,记录在“What's New”文档中

功能发布系列的关键特征

  • 同一个功能发布系列内的安装不会与其他功能发布系列安装冲突(即它们可以并行安装)
  • 同一个功能发布系列内的安装可以更新到该系列中的后续微版本,而无需重新安装或对先前安装的组件进行任何其他更改

基线功能发布的关键特征

  • 在基线功能发布中,`sys.version_info.feature_complete == False`
  • 在基线功能发布中,`sys.version_info.micro == 0`
  • 基线功能发布可能包含风险较高的语言和解释器更改,例如语法修改、解释器和标准库内部的主要重构,或可能具有对其他现有功能产生意外副作用风险的侵入性功能添加
  • 在基线功能发布中引入的功能是唯一允许依赖 `sys.version_info` 作为其功能可用性的唯一运行时指标的功能

关于功能发布系列和基线功能发布的关键预期

  • 大多数公共项目将仅积极测试一个发布系列中最新的微版本
  • 许多(或大多数?)公共项目将在初始基线功能发布之后才将新功能发布添加到其测试矩阵中,这使得解决需要提供新标志或 API 以显式选择旧行为(在默认行为已更改后)的问题变得困难。
  • 具有已知目标环境的私有项目将针对其实际使用的微版本进行测试
  • 大多数私有项目也将在初始基线功能发布之后才考虑迁移到新功能发布系列,这再次带来了问题,如果其问题的解决需要 API 添加。

本 PEP 中提案的关键动机是,上述公共和私有项目行为不是新的期望:它们是对 CPython 发布系列当前被更广泛社区处理方式的描述。因此,PEP 代表了调整我们的发布策略和流程以更好地匹配更广泛社区当前处理方式的尝试,而不是改变我们的流程,从而使更广泛的社区需要适应我们,而不是反过来。

增量功能发布

增量功能发布是本 PEP 提出的关键新流程增量。它们受到与现有维护发布相同的严格运行时兼容性要求,但围绕 API 添加和增强的策略会更宽松一些

  • 可以在任何标准库模块(包括内置模块)中添加新的公共 API
  • 在功能检测要求下,可以在现有 API(包括内置模块)中添加新的可选参数
  • 可以在稳定的 C ABI 中添加新的公共 API(带有适当的版本保护)
  • 可以在 CPython C API 中添加新的公共 API
  • 经发布经理批准,可以对现有 API 和语法结构进行向后兼容的可靠性改进
  • 经发布经理批准,可以对现有 API 和语法结构整合性能改进

此政策变更的目的是允许更及时地交付新(以及现有!)语言功能的用户体验改进,而不是要求用户承担等待并升级到下一个功能发布系列的固有延迟和成本。

它还被设计成,可以将向下一个基线功能发布添加功能的批准与是否将其提供给当前发布系列的下一个增量功能发布的问题分开考虑,这可能允许第一项任务由志愿者贡献者完成,而后者活动可以由付费贡献者处理(例如,商业 Python 重分发商的客户可能要求他们的供应商回溯某个功能,或者核心开发人员可以提供合同性的回溯)。(在对待错误修复时,以这种方式进行限制可能会存在伦理问题,但这些问题不适用于新功能的向后移植)。

增量功能发布的关键特征

  • 在增量功能发布中,`sys.version_info.feature_complete == False`
  • 在增量功能发布中,`sys.version_info.micro != 0`
  • 在增量功能发布中添加的所有 API 必须支持高效的运行时功能检测,而不依赖于 `sys.version_info` 或运行时代码对象内省。在大多数情况下,对受影响模块进行简单的 `hasattr` 检查即可达到此目的,但如果不行,则需要作为功能添加的一部分实现替代方法。该领域的先例包括 `pickle.HIGHEST_PROTOCOL` 属性、`hashlib.algorithms_available` 集合以及 `os` 模块已经提供的用于平台相关能力检测的各种 `os.supports_*` 集合。
  • 为了在混合版本环境中保持 pickle 兼容性,并为了在同一发布系列内更轻松地进行跨多个 API 版本的兼容性测试,在增量功能发布中添加的所有 API 必须支持下一节所述的新 `sys.feature_limit` 设置。

关于增量功能发布的关键预期

  • “升级时不破坏现有安装”仍然是所有微版本的一个关键要求,即使具有更宽松的变更包含策略。
  • 更具侵入性的更改仍应推迟到下一个基线功能发布。
  • 公共 Python 项目如果开始依赖在增量功能发布中添加的功能,应适当设置其 `Python-Requires` 元数据(项目已经在必要时这样做 - 例如 `aiohttp` 因早期版本中 `asyncio.get_event_loop()` 的问题而明确要求 3.5.3 或更高版本)。

某些标准库模块也可能对增量功能发布中可接受的更改施加自己的限制(例如,只有基线功能发布才能向 `hashlib.algorithms_guaranteed` 添加新的哈希算法 - 增量功能发布仅允许向 `hashlib.algorithms_available` 添加算法)。

在增量功能发布之间维护互操作性

使用 Python 的 `pickle` 模块在不同 Python 版本之间交换信息是一种常见做法。在发布系列之间,这种兼容性预计只单向运行(即,排除已弃用的 API,Python “X.Y+1” 进程应该能够读取由 Python “X.Y” 进程生成的 pickle 存档,但反之则不行,因为较新的存档可能引用旧版本中不存在的属性和参数)。

然而,在同一个发布系列中,预计它会在两个方向上都成立,因为“无新功能”策略意味着几乎所有在 Python “X.Y.Z+1” 上创建的 pickle 存档都可以被 Python “X.Y.Z” 进程读取。

同样,Python 库和应用程序通常只针对发布系列的最新版本进行测试,这通常足以使代码在同一系列中的早期版本上正常工作。

允许在后来的“X.Y.Z”版本中添加功能而不提供关闭方式将对这些常见做法造成问题,因为在 CPython 版本“X.Y.Z”上测试时正常工作的库或应用程序,如果使用了“X.Y.Z”中新引入的功能,则会在早期版本上失败,并且它创建的任何依赖于这些新接口的 pickle 存档也可能无法在旧版本上读取。

为了帮助解决这些问题,将添加一个新的 `sys.feature_limit` 属性,它是一个结构化序列,对应于 `sys.version_info` 的前三个字段(`major`、`minor`、`micro`)。

一个新的 CLI 选项(`--feature-limit X.Y.Z`)和环境变量(`PYTHONFEATURELIMIT=X.Y.Z`)将用于设置此属性。 `PyCoreConfig` 结构也将获得一个新字段。

wchar_t *feature_limit;

如果未明确设置限制,则默认值为 `sys.version_info` 的前三个字段。如果限制值超出 `sys.version_info[:2]` 的下界和 `sys.version_info[:3]` 的上界,它将被限制在这些边界内,必要时用零填充。

例如,给定当前版本为“3.9.3”,名义限制将转换为运行时 `sys.feature_limit` 值如下

3 => (3, 9, 0)
3.8.1 => (3, 9, 0)
3.9 => (3, 9, 0)
3.9.2 => (3, 9, 2)
<unset> => (3, 9, 3)
3.9.3 => (3, 9, 3)
3.9.4 => (3, 9, 3)
4 => (3, 9, 3)

回溯到增量功能发布的新 API 预计将包含一个删除该 API 的 guard,如果功能限制太低。

def feature_api():
    ...

_version_feature_api_added = (3, 9, 1)
if _version_feature_api_added > sys.feature_limit:
    del feature_api

类似地,新的参数预计将包含一个 guard,该 guard 会调整函数签名以匹配旧的签名。

def feature_api(old_param1, old_param2, new_param=default):
    """Updated API docstring"""
    ...

_version_feature_api_changed = (3, 9, 1)
if _version_feature_api_changed > sys.feature_limit:
    _new_feature_api = feature_api
    def feature_api(old_param1, old_param2):
        """Legacy API docstring"""
        return _new_feature_api(old_param1, old_param2)

这样组织 guard 将使主开发分支和回溯分支之间的代码结构尽可能相似,以便将来的错误修复仍然可以自动回溯。

预计将来会添加便捷函数和/或额外的自动化测试来帮助确保这些回溯的 API 得到适当的 guard,但似乎最好等到有具体的实际示例来驱动这些 API 和自动化测试的设计,而不是仅仅基于假设的示例来设计它们。

功能完整发布和后续维护发布

给定功能发布系列的“功能完整”版本将在增量功能发布的正常策略下开发,但会有一个区分特征

  • 在功能完整版本中,`sys.version_info.feature_complete == True`

任何后续的维护和仅安全修复版本也将设置该标志,并可能被非正式地称为“功能完整版本”。然而,对于发布系列的定义而言,“功能完整”版本是第一个将该标志设置为“True”的版本。

关于临时 API 的拟议政策调整

为了帮助提高临时 API 管理的一致性,本 PEP 提出临时 API 应遵循给定发布系列的“功能完整”发布后的常规向后兼容性要求。

临时 API 管理的其他方面将保持不变,因此只要 API 保持临时状态,常规向后兼容性要求将不适用于基线和增量功能发布中的该 API。

根据对自 3.0.0 版本以来 CPython 微版本中已记录的 API 添加和更改的分析,预计此政策将为最终用户提供更大的清晰度(因为即使是临时 API 在功能完整发布后也将对该发布系列稳定),而对标准库维护者的实际影响则很小。

  • 21 个 3.x.1 版本添加/更改说明
  • 30 个 3.x.2 版本添加/更改说明
  • 18 个 3.x.3 版本添加/更改说明
  • 11 个 3.x.4 版本添加/更改说明
  • 1 个 3.x.5 版本添加/更改说明
  • 0 个 3.x.6+ 版本添加/更改说明

当需要进行基线发布后的更改时,大部分更改都发生在最初的两个维护版本中,而这两个版本总是在基线发布后 12 个月内发生。

(注意:这些计数不只是针对临时 API - 它们涵盖了所有在基线发布后进行了语义更改并被认为有必要在文档中涵盖的 API。为避免重复计算更改,数字不包括“What's New”部分中的任何更改标记)。

动机

本 PEP 中更改的动机与 PEP 596 中的更改动机基本相同:当前 18-24 个月的功能发布间隔存在许多不良后果,特别是对标准库(有关详细信息,请参阅 PEP 596)。

本 PEP 对 PEP 596 中特定提案的担忧是,它使积极支持的 Python 分支数量翻倍,增加了整个 Python 社区的兼容性测试矩阵的复杂性,在不使用稳定 ABI 的情况下增加了需要上传到 PyPI 的二进制 Python wheel 的数量,并且总的来说,很有可能给整个 Python 生态系统带来相对较高的额外成本。

本 PEP 采取的观点是,存在一种替代方法,可以提供快速功能发布的绝大多数好处,而无需承担相关成本:我们可以将当前的 X.Y.0“功能冻结”分为两部分,使得基线 X.Y.0 发布仅强制执行“运行时兼容性冻结”,而完整的标准库功能冻结则推迟到发布系列生命周期的后期。

注意事项和局限性

此提案不追溯适用于 Python 3.8 - 它仅针对 Python 3.9 及更高版本提出。

发布日期最多可由发布经理酌情提前或推迟一个月,具体取决于发布团队的可用性以及其他事件的时间(例如 PyCon US 或年度核心开发冲刺)。然而,本提案的目标之一是为贡献者和最终用户提供一致的年度节奏,因此调整应该是罕见的。

本 PEP 没有规定发布系列内微发布的具体节奏 - 它只规定了发布系列生命周期阶段(预 Alpha、Alpha、Beta、功能发布、错误修复、安全修复)之间大致的时间线。每个阶段内的微发布数量由该系列的发布经理决定,具体取决于他们和该系列其他发布团队准备承担相关工作的频率。

然而,为了示例时间线的缘故,PEP 假设每季度进行一次微发布(Python 3.6 和 3.7 使用的节奏,介于某些历史发布系列使用的每年两次的节奏和 Python 3.8 和 3.9 计划的每月节奏之间)。

设计讨论

为什么提出此提案而不是仅仅进行更频繁的基线功能发布?

基线功能发布涉及的文件系统布局更改和其他固有的不兼容更改会给更广泛的 Python 社区的许多部分带来额外工作。

将这些布局更改与 Python 版本号方案分离开来本身也会涉及向后不兼容的更改,并调整社区关于哪些版本可以覆盖安装以及哪些可以并行安装的期望。

我们也没有简单的方法来向社区传达支持周期的差异,例如“仅支持 Python 版本 X.Y 直到 X.Y+1 发布,但支持 X.Z 直到 X.Z+2 发布”。

因此,本 PEP 的基本假设是,绝大多数 Python 用户根本不需要关心我们正在更改发布策略,而唯一受影响的人是那些热切等待标准库改进(和其他向后兼容的解释器增强)的人,以及那些需要在复杂部署环境中管理任务关键型应用程序的人。

对 Python 库开发的影响

许多 Python 库(包括开源和专有库)目前采用的做法是仅针对项目仍支持的每个功能发布系列中最新的微版本进行测试。

本 PEP 中的设计假设是,这种做法将在发布系列的“功能发布”阶段继续遵循,其预期是任何选择采用新功能发布系列但尚未功能完整的人将密切跟踪增量功能发布。

支持前一个功能发布系列的库不太可能采用在增量功能发布中添加的功能,如果它们采用了这样的功能,那么任何相关的回溯兼容性策略都应该以在同一发布系列中较早版本上同样有效的方式实现。

对拟议的科学 Python 生态系统支持周期的影响

基于在 SciPy 2019 上的讨论,目前正在起草一项 NEP [2],以在科学 Python 生态系统中定义一个关于放弃支持旧 Python 版本的通用约定。

虽然该策略的确切表述仍在讨论中,但初步提案非常简单:支持过去 42 个月内发布的任何 Python 功能发布。

对于 18 个月的发布周期,这意味着始终支持至少最近的两个功能发布,然后在 X.(Y+2).0 发布后约 6 个月内放弃对所有 X.Y.z 版本的支持。这意味着大约每两年有 6 个月的时期,支持最近的三个功能发布。

对于 12 个月的发布周期,这意味着始终支持至少最近的三个功能发布,然后在 X.(Y+3).0 发布后约 6 个月内放弃对所有 X.Y.z 版本的支持。这意味着一年中有一半的时间将支持最近的四个功能发布。

对于 24 个月的发布周期,42 个月的支持周期意味着始终支持至少最新的功能发布,然后在 X.(Y+1).0 发布后约 18 个月内放弃对所有 X.Y.z 功能发布的支持。这意味着大约每两年有 6 个月的时期,只支持一个功能发布(并且该时期与 X.(Y+2).0 基线功能发布的预发布测试期重叠)。

对于本 PEP 中的提案来说,重要的是,该支持期将遵守库开发人员建议的策略,即在最新发布系列达到功能完整状态之前,继续支持前一个发布系列:在基线功能发布后 18 个月放弃支持,大致相当于在功能完整发布后 6 个月放弃支持,而无需精确跟踪哪个发布标记了该系列的功能完整。

对简单部署环境的影响

就本 PEP 而言,“简单”部署环境是指任何可以轻松确保所有目标环境都更新到新的 Python 微版本(或至少在更高层应用程序版本推出之前),并且没有要求旧 Python 版本能够可靠地读取使用新 Python 版本生成的 pickle 流,因此进行的任何预发布测试只需要针对单个 Python 微版本。

最简单的此类情况是个人使用的脚本,其中测试和目标环境是完全相同的环境。

类似的简单环境是容器化 Web 服务,其中在 CI 管道和部署上使用的 Python 容器相同,以及任何捆绑自身 Python 运行时而不是依赖目标系统上已有的 Python 部署的应用程序。

对于这些用例,本 PEP 不应有任何重大影响 - 只需测试一个微版本,无论该版本是否功能完整。

对复杂部署环境的影响

就本 PEP 而言,“复杂”部署环境是指不满足上述“简单部署”标准的用例:在新应用程序版本与同一发布系列中的两个或多个不同微版本结合使用作为部署过程的一部分,而不是一次只针对一个微版本。

如果本 PEP 中的提案能有效降低功能交付延迟,那么可以预期使用尚未功能完整的发布系列的开发人员将实际利用新功能。这意味着针对较新的增量功能发布进行测试,对于与基线功能发布和较旧增量功能发布的兼容性测试,其有效性甚至不如针对较旧维护版本的较新维护版本进行测试。

处理这种情况的一种选择是简单地禁止使用新的 Python 版本,直到该系列达到“功能完整”状态。许多组织在对待新的功能发布系列时,实际上已经采用了这种策略,在原始发布几个月或几年后才接受到操作环境。如果采用此策略,那么这些组织仍然可以每两年采用一个新的 Python 版本 - 它将基于功能完整版本的可用性,而不是基线功能发布。

一种不那么严格的替代方法是采用拟议的 `PYTHONFEATURELIMIT` 设置来启用分阶段迁移到新的增量功能发布。

  • 最初推出 Python X.Y.0,并在 CI 和部署上设置 `PYTHONFEATURELIMIT=X.Y.0`。
  • 将 Python X.Y.1 推送到 CI,同时保持 `PYTHONFEATURELIMIT=X.Y.0` 设置。
  • 在 CI 成功结果的基础上,将 Python X.Y.1 部署到生产环境。
  • 将部署环境更新为设置 `PYTHONFEATURELIMIT=X.Y.1`。
  • 仅当所有部署环境都已更新后,才在 CI 中设置 `PYTHONFEATURELIMIT=X.Y.1`。
  • 对新发布(包括发布系列的截至功能完整的版本)重复此过程。
  • 一旦系列功能完整,要么继续采用相同的流程以保持一致性,要么停止更新 `PYTHONFEATURELIMIT` 并将其保留在功能完整版本号。

功能添加周期的持续时间

本 PEP 提议将功能添加限制在初始基线功能发布后 12 个月内。

这样做的主要动机是与 Ubuntu LTS 时间同步,以便 Python 3.9.x 系列的功能完整版本在 2021 年 10 月发布,准备包含在 Ubuntu 22.04 版本中。(其他 LTS Linux 发行版,如 RHEL、SLES 和 Debian,没有固定的发布节奏,因此它们可以更轻松地调整其 LTS 时间以与稳定版本的输入保持一致。Canonical 特意在自己的发布周期中没有给自己这种灵活性)。

12 个月的添加周期则源于 2019 年 10 月发布 Python 3.8.0 和 2021 年 10 月发布的最后一个 Python 3.9.x 增量功能发布之间的时间被平均分配给预发布开发和后续增量功能发布。

这方面,本 PEP 可以采纳 PEP 596 提案的一部分,将该划分调整为大约 9 个月的预发布开发,以及大约 15 个月的增量功能发布。

  • 2019-11:3.9.0a1
  • … 由发布经理决定的其他 alpha 版本
  • 2020-03:3.9.0b1
  • 2020-04:3.9.0b2
  • 2020-05:3.9.0b3(锁定 ABI 兼容性的最终 Beta 版本)
  • 2020-06:3.9.0rc1
  • … 由发布经理决定的其他发布候选版本
  • 2020-07:3.9.0(BFR)
  • 2020-10:3.9.1(IFR)
  • 2021-01:3.9.2(IFR)
  • 2021-04:3.9.3(IFR)
  • 2021-07:3.9.4(IFR)
  • 2021-10: 3.9.5
  • 2022-01: 3.9.6
  • 2022-04: 3.9.7
  • 2022-07: 3.9.8
  • 2022-10:3.9.9(最终常规维护发布)
  • … 按需进行其他仅安全修复的发布
  • 2025-10:3.9.x 分支关闭

这种方法意味着仍然总是有两个或三个活动分支,只是“功能发布”阶段的时间比例会更长,而“预 Alpha”、“预 Beta”和“预发布”阶段的时间比例会更短。

  • 2019-04 -> 2019-10:3.9.0 预 Alpha 版、3.8.0 预发布版、3.7.x 维护版
  • 2019-10 -> 2020-03:3.9.0 预 Beta 版、3.8.x 维护版
  • 2020-03 -> 2020-07:3.10.0 预 Alpha 版、3.9.0 预发布版、3.8.x 维护版
  • 2020-07 -> 2021-10:3.10.0 预 Alpha 版、3.9.x 功能发布、3.8.x 维护版
  • 2021-10 -> 2022-03:3.10.0 预 Beta 版、3.9.x 维护版
  • 2022-03 -> 2022-07:3.11.0 预 Alpha 版、3.10.0 预发布版、3.9.x 维护版
  • 2022-07 -> 2023-10:3.11.0 预 Alpha 版、3.10.x 功能发布、3.9.x 维护版
  • 2023-10 -> 2024-03:3.11.0 预 Beta 版、3.10.x 维护版
  • 2024-03 -> 2024-07:3.12.0 预 Alpha 版、3.11.0 预发布版、3.10.x 维护版
  • … 等等

未发布预 Alpha 版本的持续时间

在本 PEP 的基线提案中,提议的时间表仍然包括我们长达 18 个月没有从主 git 分支发布新版本的时期(例如,3.9.0b1 将在 2020-05 分支,而 3.10.0a1 要到 2021-11 才发布)。它们只是允许在 12 个月内将更广泛的更改回溯到最新的维护分支。

将 Beta 分支点提前到发布系列生命周期早期的提案变体会将无直接发布时期增加到 21 个月——唯一的直接从主分支发布版本时期将是在前一个发布系列最后一个增量功能发布和几个月后的 Beta 分支点之间的相对短暂窗口。

虽然将年度节奏在“大型基础性增强”和“有针对性的低风险 API 可用性改进”之间交替进行是此提案的一项刻意特征,但在上一个发布系列分支后不久就进行了更改的情况下,等待这么长时间以获得反馈似乎仍然很奇怪。

处理此问题的另一种方法是,在功能添加期间开始为下一个基线功能发布发布 Alpha 版本(类似于 PEP 596 提议在 Python 3.8.0 发布候选周期期间开始发布 Python 3.9.0 Alpha 版本)。

然而,与其在策略层面设定具体的时间表,不如将这个决定留给各个发布经理,根据他们正在管理的版本的具体拟议更改来决定。

为什么不直接切换到完全的语义化版本控制?

如果这是一个新语言的版本设计文档,它使用语义化版本控制:本 PEP 中关于基线功能发布的策略将应用于 X.0.0 版本,增量功能发布的策略将应用于 X.Y.0 版本,维护发布的策略将应用于 X.Y.Z 版本。

Python 特有的问题在于,所有关于并行安装支持和 ABI 兼容性定义的策略和属性目前都与版本号的前两位相关联,并且近三十年来一直如此。

因此,将首先引入增量功能发布的策略问题与使版本号方案更好地匹配不同发布类型的语义的技术问题分开处理是合理的。

如果本 PEP 中的提案被 Python 3.9 的指导委员会接受,那么解决该技术问题的更好时机将是随后的 2022 年 10 月基线功能发布,因为选择“Python 4.0”(错误地检查主版本号是否精确为 3 而不是 3 或更高)或“Python 3.10”(代码错误地假定次版本号始终包含恰好一个十进制数字)已经存在固有的兼容性风险 [1]

虽然本 PEP 的文本假设 2022 年发布的版本将是 3.10(因为 PEP 作者个人认为这是更合理和最有可能的选择),但在这两个决定方面都存在复杂的利弊,并且本 PEP 确实为选择“Python 4.0”选项增加了一个潜在的优点(但需要注意的是,我们还需要修改受影响的安装布局和兼容性标记,使其仅考虑主版本号,而不是主版本号和次版本号)。

如果将来提出并接受了这样的版本号更改,那么上面给出的示例 3.10.x 时间表将改为以下 4.x 系列时间表

  • 2021-11:4.0.0a1
  • … 由发布经理决定的其他 alpha 版本
  • 2022-05:4.0.0b1
  • … 由发布经理决定的其他 beta 版本
  • 2022-08:4.0.0bX(锁定 ABI 兼容性的最终 Beta 版本)
  • 2022-09:4.0.0rc1
  • … 由发布经理决定的其他发布候选版本
  • 2022-10:4.0.0(BFR)
  • 2023-01:4.1.0(IFR)
  • 2023-04:4.2.0(IFR)
  • 2023-07:4.3.0(IFR)
  • 2023-10:4.4.0(IFR)
  • 2024-01: 4.4.1
  • 2024-04: 4.4.2
  • 2024-07: 4.4.3
  • 2024-10:4.4.4(最终常规维护发布)
  • … 按需进行其他仅安全修复的发布
  • 2027-10:4.x 分支关闭

以及 5 年时间表预测将如下所示

  • 2019-04 -> 2019-10:3.9.0 预 Alpha 版、3.8.0 预发布版、3.7.x 维护版
  • 2019-10 -> 2020-05:3.9.0 预 Beta 版、3.8.x 维护版
  • 2020-05 -> 2020-10:4.0.0 预 Alpha 版、3.9.0 预发布版、3.8.x 维护版
  • 2020-10 -> 2021-10:4.0.0 预 Alpha 版、3.9.x 功能发布、3.8.x 维护版
  • 2021-10 -> 2022-05:4.0.0 预 Beta 版、3.9.x 维护版
  • 2022-05 -> 2022-10:5.0.0 预 Alpha 版、4.0.0 预发布版、3.9.x 维护版
  • 2022-10 -> 2023-10:5.0.0 预 Alpha 版、4.x.0 功能发布、3.9.x 维护版
  • 2023-10 -> 2024-05:5.0.0 预 Beta 版、4.x.y 维护版
  • 2024-05 -> 2024-10:6.0.0 预 Alpha 版、5.0.0 预发布版、4.x.y 维护版
  • … 等等

参考资料


来源:https://github.com/python/peps/blob/main/peps/pep-0598.rst

最后修改:2025-02-01 08:59:27 GMT