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

Python 增强提案

PEP 605 – CPython 的滚动功能发布流

作者:
Steve Dower <steve.dower at python.org>, Alyssa Coghlan <ncoghlan at gmail.com>
讨论地址:
Discourse 讨论线程
状态:
已拒绝
类型:
信息
创建日期:
2019-09-20
Python 版本:
3.9
历史记录:
2019-10-01, 2019-10-06, 2019-10-20

目录

拒绝通知

本 PEP 被 PEP 602 拒绝。潜在的 alpha/beta 交替被认为过于混乱,并且两个版本之间的两年周期被认为太长。

摘要

长期以来,CPython 的名义功能发布周期一直是“每 18-24 个月”,近年来,一直相当稳定地在“18 个月”的窗口内。 PEP 607 提供了一些关于这种周期选择带来的问题以及更改它时需要考虑的一些风险的通用背景。

本 PEP 中的提案旨在允许 CPython 的用户群自行选择加入两个不同的但重叠的组

  • 使用每 24 个月发布一次的稳定功能版本(以及相关的维护版本流)的用户;以及
  • 采用新的滚动发布流的早期使用者,该发布流取代了以前的 CPython 预发布流程

作为本提案的一部分,针对 beta 版本的用法指南将变为“仅适用于具有足够健壮的兼容性测试和运营监控能力的环境的生产环境”,而不是当前的无条件“不适用于生产环境”。

同样,针对 alpha 版本的指南将被修改为声明“用于库兼容性测试和创建 ABI 兼容的二进制制品”,而不是仅仅说“不适用于生产环境”。

PEP 作者相信,可以通过修改 CPython 预发布管理流程来实现这些结果,如下面的“提案”部分所述。

本 PEP 还建议调整 X.Y.0 版本的频率,以使每个新的版本系列在每两年的 8 月开始(从 2021 年开始,大约在 Python 3.8.0 发布两年后)。

未来发布计划示例

根据本提案,Python 3.9.0a1 将于 2019 年 12 月发布,在 2019 年 10 月的 Python 3.8.0 基线功能版本发布后两个月。

假设对 CPython 全 ABI 没有进一步的突破性变更,3.9.0b2 版本将在 2 个月后的 2020 年 2 月发布,一直持续到 2021 年 4 月的 3.9.0b9 版本。

只要引入对 CPython 全 ABI 的突破性变更,第一个包含该变更的预发布版本将被标记为 alpha 版本。

3.9.0rc1 将于 2021 年 6 月发布,3.9.0rc2 将于 2021 年 7 月发布,然后最终版本将作为 3.9.0 发布,于 2021 年 8 月发布。

该周期将在 2021 年 10 月重新开始,发布 3.10.0a1(在创建 3.9.x 维护分支 4 个月后)。

维护版本的具体时间表由发布团队决定,但假设 3.9.x 的维护版本也每隔一个月发布一次(与 3.10.0 beta 版本错开),那么整体发布时间线将如下所示

  • 2019-12: 3.9.0a1
  • 2020-02: 3.9.0b2
  • … 每隔一个月发布 beta 或 alpha 版本
  • 2021-04: 3.9.0b9
  • 2021-06: 3.9.0rc1 (功能冻结,ABI 冻结,pyc 格式冻结)
  • 2021-07: 3.9.0rc2
  • 2021-08: 3.9.0
  • 2021-09: 3.9.1, 3.8.x (最终 3.8.x 二进制维护版本)
  • 2021-10: 3.10.0a1
  • 2021-11: 3.9.2
  • 2021-12: 3.10.0b2
  • … beta 和维护版本继续交替发布
  • 2023-04: 3.10.0b10
  • 2023-05: 3.9.11
  • 2023-06: 3.10.0rc1 (功能冻结,ABI 冻结,pyc 格式冻结)
  • 2023-07: 3.10.0rc2, 3.9.12
  • 2023-08: 3.10.0
  • 2023-09: 3.10.1, 3.9.13 (最终 3.9.x 二进制维护版本)
  • 2023-10: 3.11.0a1
  • 2023-12: 3.11.0b2
  • … 等等

如果我们假设在 3.9.0a5 和 3.9.0a7 版本中发布了两个额外的预发布版本,它们引入了对 CPython 全 ABI 的突破性变更,那么整体时间表将如下所示

../_images/pep-0605-example-release-calendar.png

图 1. 预发布流程变更对时间表的影响。

在这个模型中,始终存在两个或三个活动的维护分支,这在这一点上保留了现状。主要区别在于,除了为稳定的维护分支提供预构建的二进制文件之外,我们还将开始鼓励发布者为滚动预冻结版本提供预构建的二进制文件。

../_images/pep-0605-overlapping-support-matrix.png

图 2. 18 个月周期与 24 个月周期中的测试矩阵。

针对 CPython 全 ABI 的软件包发布者,如果选择为滚动预冻结版本提供预构建的二进制文件,至少需要在 3.9.0a1 版本发布后构建新的 wheel 归档文件。是否需要在后续的 alpha 版本(例如,示例时间表中的 3.9.0a5 或 3.9.0a7 版本)发布后发布更新的二进制文件,将取决于他们是否实际上受到这些后续版本中 ABI 突破的影响。

与现状一样,所有希望为最终版本提供预构建的二进制文件的软件包发布者都需要在 ABI 冻结日期之后构建新的 wheel 归档文件。与现状不同的是,此日期将由第一个候选版本的发布明确标记,并且它发生得足够早,可以给发布者几个月的时间来为最终版本做好准备。

未来发布公告示例

如果本 PEP 被接受,用于将更新的预发布管理流程传达给最终用户的首要渠道将是 Python 3.9 中的新内容文档以及发布公告本身。

本节提供了一些可用于这些目的的文本初始草案。

"Python 3.9 中的新内容"条目建议

以下小节将添加到 Python 3.9 中的新内容文档中,然后从每个 Python 3.9 alpha 和 beta 公告中链接到它。

PEP 605: 预发布管理流程的变更

PEP 605 中所述,预发布管理流程已更新,以生成一系列滚动发布的 beta 版本,这些版本被认为适用于具有足够健壮的集成测试和运营监控能力的环境的生产环境。

在这个新的滚动模型下,alpha 和 beta 版本作为组合的“预冻结”阶段的一部分交织在一起,alpha 版本表示 CPython 全 ABI 的突破,这可能需要重新编译扩展模块或嵌入式应用程序,而 beta 版本表示与之前的预发布版本完全的二进制兼容性。

与之前的版本不同,积极鼓励发布 3.9.0 alpha 和 beta 版本的预构建二进制文件,因为在 CPython 全 ABI 冻结之前构建和加载扩展模块时,现在会设置一个新的预发布 ABI 标志 (“p”),确保所有此类预冻结扩展模块构建将在冻结后的解释器构建中被忽略。

CPython 全 ABI 将在 3.9.0rc1 中冻结,并且预发布标志将从 ABI 标志中删除,预计该版本将在最终 3.9.0 版本发布前 2 个月发布(有关确切的目标日期,请参考 PEP 596 中的发布时间表)。

对于应用程序开发人员,迁移到滚动发布流提供了在下一个稳定版本发布之前积极参与标准库和参考解释器的增强设计和开发的机会。它还提供了在稳定版本发布之前一年或更长时间内从解释器性能增强中获益的机会。

对于发布预构建 wheel 归档文件的库开发人员,除了 3.8 稳定版本系列之外,选择支持 3.9.x 滚动发布流不需要任何特定操作,如果项目已经发布纯 Python wheel(标记为 py3-none-any),或者针对稳定 C ABI 构建(标记为 cp38-abi3-<platform>,或来自早期 CPython 3.x 版本的等效标记)。这些相同的 wheel 归档文件也将在后续的 3.9 稳定版本系列中可用。

对于发布针对 CPython 全 ABI 构建的预构建 wheel 归档文件的库开发人员,需要在 CPython 全 ABI 冻结之后(即使用 3.9.0rc1 或更高版本)构建 3.9 稳定版本系列的二进制文件。

这些库的开发人员也可以选择通过针对 3.9.0a1 版本(或后续的 beta 版本)构建并按正常方式发布结果来支持滚动发布流。

理想情况下,这种方式构建的二进制文件将一直可以使用到最后一个预冻结版本。但是,如果项目在预冻结期间受到 CPython C ABI 完整更改的影响,则需要发布维护更新,以针对更改相关接口的 alpha 版本重新构建受影响的二进制文件。在这些情况下,应在项目元数据中添加相应的 Python-Requires 条目。例如,如果项目受到 3.9.0a5 中引入的 ABI 更改的影响,则要添加的 Python-Requires 条目将是

Python-Requires: >= "3.9.0b6"; python_version == "3.9" and full_python_version != "3.9.0a5"

(此附加元数据确保更新的版本不会安装在 3.9 系列中提供较旧 ABI 变体的早期预发布版上)

至于应用程序开发人员,选择支持滚动发布流的库开发人员将有机会在新的和更新的 API 设计被锁定在稳定版本中多年(或在它们被包含在稳定版本系列中的临时 API 中)之前提供反馈。

3.9.0a1 版本的公告文本示例

这是 Python 3.9 的第一个预览版。作为 alpha 版本,它旨在用于库和应用程序兼容性测试以及创建 ABI 兼容的二进制工件。不建议在生产环境中使用它。

预发布管理流程的变更

CPython 已切换到新的预发布管理流程,该流程旨在生成一系列滚动发布的 beta 版本,这些版本被认为适合在具有足够强大集成测试和操作监控功能的环境中用于生产。

3.9 系列相较于 3.8 的主要新功能

Python 3.9 的许多新功能仍在规划和编写中。在已经实施的主要新功能和更改中

  • (嘿,核心开发人员或滚动发布流的用户,如果您发现的重要功能未在此列表中,请告知 <<发布经理>>。)

Python 3.9 的下一个预发布版预计为 3.8.0b2,目前计划于 2020 年 2 月 2 日发布。

3.9.0b2 版本的公告文本示例

这是 Python 3.9 的第二个预览版。作为 beta 版本,它与之前的 3.9.0a1 版本完全二进制兼容。仅建议在具有足够强大的集成测试和操作监控功能的环境中用于生产。

(其余部分与 3.9.0a1 公告相同,更新了已实施的更改,下一个预期版本为 3.9.0b3)

3.9.0a5 (中间 alpha 版本) 的公告文本示例

这是 Python 3.9 的第五个预览版。作为 alpha 版本,它与之前的 3.9.0b4 版本不完全二进制兼容。此版本旨在用于库和应用程序兼容性测试以及创建 ABI 兼容的二进制工件。不建议在生产环境中使用它。

3.9.0b4 和 3.9.0a5 之间 CPython ABI 的重大变更

  • PyObject 结构中添加了新字段 ob_example
  • PyTypeObject 结构中删除了临时字段 tp_example

支持滚动发布流并需要重建以恢复二进制兼容性的项目应在其更新的版本中添加以下元数据

Python-Requires: >= "3.9.0b6"; python_version == "3.9" and full_python_version != "3.9.0a5"

(其余部分与 3.9.0a1 公告相同,更新了已实施的更改,下一个预期版本为 3.9.0b6)

3.9.0rc1 的公告文本示例

这是 Python 3.9 的第一个候选版本。作为候选版本,此版本现在功能完整,CPython ABI 现已冻结,并且已从 ABI 兼容性标志中删除预发布标记。仅建议在具有足够强大的集成测试和操作监控功能的环境中用于生产。

为最终 3.9.0 版本做准备

现在 CPython ABI 已冻结,建议面向该 ABI 的库开发人员构建并发布针对稳定 3.9.x 系列的二进制文件。

尚未针对滚动发布流进行测试的应用程序开发人员建议针对候选版本测试其应用程序,并报告端口指南(链接到相关的“新功能”部分)中尚未提及的任何兼容性回归。

计划在 2021 年 7 月 2 日发布第二个候选版本,然后计划在 2021 年 8 月 2 日发布最终的 3.9.0 版本。

3.9 系列相较于 3.8 的主要新功能

此版本中的一些主要新功能和更改

  • (嘿,核心开发人员或滚动发布流的用户,如果您发现的重要功能未在此列表中,请告知 <<发布经理>>。)

动机

当前的 CPython 预发布和发布管理流程是在自动化持续集成和操作监控系统还相对不成熟的时代开发的。从那时起,许多组织已经采用了部署模型,允许他们在不增加比对任何其他代码更改所产生的风险更大的风险的情况下,合并新的 CPython 功能版本。较新的部署模型(例如轻量级任务特定应用程序容器)也使在 CI 管道中将应用程序与语言运行时组合起来变得更加容易,然后将它们保留在一起,直到整个容器映像稍后被更新的映像替换。

考虑到环境中的这些变化,PEP 602 提出通过将 CPython 功能版本的发布频率从每 18-24 个月增加到每 12 个月来缩短 Python 标准库和 CPython 参考解释器的功能交付延迟。

不幸的是,对于许多组织来说,采用新 Python 版本的成本不会随着版本中更改次数的减少而自动降低,因为主要成本与解决任何发现的问题无关;主要成本与搜索问题有关。此搜索可能涉及对软件系统的手动测试、对书面材料的人工审查以及其他活动,其中所需时间随着现有系统的大小而变化,而不是随着 Python 版本之间的更改数量而变化。

对于第三方库开发人员来说,成本主要与广泛使用的不同 Python 版本的数量有关。这目前往往受 python-dev 仍然积极维护哪些版本以及哪些版本是特定重新分发者提供的最新版本(其中 Debian、Ubuntu LTS 和 RHEL/CentOS 系统 Python 版本特别受欢迎的开发目标)的共同影响。除了针对更多 Python 版本进行测试的基本 CI 成本外,广泛使用更多变体可能会使确定故障报告是项目中的实际错误还是报告用户环境中的问题变得更加困难。

PEP 602 建议受影响的组织和项目只需切换到采用每隔一个或三个 CPython 版本,而不是试图采用每个版本,但这会带来自己的需要解决的新问题,无论是实际问题(例如,如果我们期望用户定期跳过版本,则弃用需要涵盖多个版本)还是文化问题(例如,随着大量版本处于活跃使用中,开源库维护人员更有可能收到仅在他们自己未使用的 Python 版本上发生的错误报告)。

PEP 598 是此 PEP 作者之一提出的最初尝试,该尝试提出了一种替代方案,通过采用语义版本控制风格的策略来减少功能交付延迟,该策略允许在发布系列中增量交付向后兼容的功能,直到该系列达到功能完整状态。该变体仍然具有不可取的结果,即在最终用户身上施加了可见的更改,而这些最终用户对当前的发布管理模型感到满意。

此 PEP 认为 PEP 598PEP 602 都有一个共同的缺陷:它们试图在单一发布模型的约束下满足两个截然不同的受众的需求,这会导致冲突的设计要求,以及在这些冲突的要求之间进行尴尬权衡的必要性。此 PEP 中的提案旨在通过提议创建两个不同的生产就绪发布流来避免这种缺陷,现有发布流在很大程度上保持不变,而新发布流则针对从缩短功能交付延迟中获益最多的受众进行定制。

本提案的目标

此 PEP 中的提案基于以下关键假设

  • 绝大多数 Python 用户并没有积极地要求新的语言和运行时级别功能,而只是在之前使用的版本不再受支持时、他们的 Python 提供商默认切换到提供更新版本时,或者当他们感兴趣的更改积累到足以使升级具有说服力的理由时才会进行升级。
  • 对于许多新版本的用户来说,采用新版本时出现的大部分工作不是来自语言级别的兼容性问题,而是来自组件安装级别的兼容性问题(即文件名和安装路径更改)。
  • Python 用户群中有一部分用户愿意为至少部分用例运行生产就绪的预发布版(类似于 Windows Insider 或 Debian 测试版本)。

此 PEP 中的提案的核心是更改 CPython 预发布流程,以便定期生成增量功能发布的滚动流,并确保大多数这些构建提供足够的稳定性,以适合在适当地管理的生产系统中使用。

通过采用这种方法,该提案旨在为几乎所有 Python 用户和贡献者提供更好的结果

  • 对于新增量功能发布流的用户来说,针对预发布阶段可以实现比 PEP 602 中提出的年度节奏更低的特征交付延迟;
  • 对于致力于开发新功能的核心开发人员来说,预发布版本的增加频率和采用率应该可以改善预发布反馈周期;
  • 对于已建立发布流的用户来说,预发布期间的增加采用率和改进的反馈周期应该会在第一个 X.Y.0 版本发布时提高功能成熟度,以及更高的生态系统准备程度;
  • 对于 Python 库维护人员来说,滚动发布的预发布版本将有望提供更多机会在设计问题进入完整稳定版本之前识别和解决这些问题,这比当前的预发布管理流程所能提供的机会更多;并且
  • 对于替代 Python 实现的开发人员来说,滚动发布的预发布版本可能会为扩展模块作者从完整的 CPython ABI 迁移到 Python 稳定 ABI 提供额外的动力,这也将有助于使更多生态系统与不模拟完整的 CPython C API 的实现兼容。

也就是说,我们承认,该提案并非对所有 Python 生态系统成员都有益。

  • 对于 Python 库维护者来说,本 PEP 和 PEP 602 都可能导致用户施加压力,要求他们支持更快的发布节奏。虽然本 PEP 试图通过明确标记哪些预发布版本包含可能破坏 CPython C ABI 的更改来缓解这种情况,而 PEP 602 试图通过将完整版本之间的最小时间间隔保持在 12 个月来缓解这种情况,但这并不能完全消除这个缺点;
  • 对于第三方扩展模块维护者来说,本 PEP 和 PEP 602 都可能导致用户施加压力,要求他们开始支持稳定 ABI,以便在新版本发布后尽快提供适用于新版本的 wheel 档案。这是否会造成负面影响将取决于如何向他们提出要求(如果请求是来自有兴趣支持滚动预冻结版本开发人员的礼貌贡献,这可能是积极的);
  • 对于依赖于预编译 wheel 档案可用性的已建立发布流的一些用户来说,每 12 个月采用一次新版本可能是一个可以接受的速率增加,而与最近版本使用的 18 个月周期相比,始终过渡到历史上的 18-24 个月周期的 24 个月结束将是一个不可取的速率降低。这项提案对于这些用户来说是否会造成负面影响将取决于我们是否能够说服库维护者,在整个预冻结期间支持即将发布的稳定版本是值得的,而不是等到其 API 和 ABI 被冻结。

提案

本 PEP 中提出的更改大多数仅影响预发布版本的处理。影响完整版本的一个更改是建议更改其发布节奏。

稳定版本两年发布周期

随着滚动预冻结版本的发布,这些版本可供希望使用参考解释器和标准库的最新版本的 用户使用,本 PEP 建议调整 X.Y.0 版本的频率,以便每两年在八月发布一个新的稳定版本(从 2021 年开始,大约在 Python 3.8.0 发布两年后)。

这种变化可以说是与处理预冻结发布期间提出的更改正交的,但两者之间的联系是,如果没有这些预发布管理更改,两年一次的完整版本发布节奏的缺点可能大于优点,而对于 12 个月一次的发布节奏,情况则相反(即,在实施本 PEP 中提出的预发布管理更改的情况下,12 个月一次的完整版本发布节奏的缺点会大于优点)。

将 alpha 和 beta 阶段合并为“预冻结”阶段

本 PEP 建议将预发布版本的 alpha 和 beta 阶段不再是独立的、顺序的,而是合并成一个单一的“预冻结”阶段,并在发布版本上使用单调递增的序列号。

“alpha”和“beta”名称不再表示不同的阶段,而是表示发布版本是否包含对 CPython C ABI 的破坏性更改。

  • “alpha”版本是“ABI 破坏性”版本,针对上一个预发布版本中的 CPython ABI 构建的扩展模块不一定能够正确加载。
  • “beta”版本是“二进制兼容”版本,只要这些模块符合以下额外标准,针对上一个预发布版本中的 CPython ABI 构建的扩展模块应该能够正确加载。
    • 该模块不得使用任何在本 beta 版本中删除的或以 ABI 不兼容方式更改的临时或私有 C API(无论是来自上一个稳定版本系列,还是来自正在开发的预发布版本系列)。
    • 该模块不得使用在上一个稳定版本系列中已弃用的 C API,并且在本 beta 版本中删除了。

预冻结阶段持续时间和频率

预冻结版本不是在准备新的 X.Y.0 版本时每月发布几个月,而是每两个月发布一次。

只有在即将发布的 X.Y.0 版本的两个月的发布候选版本期间才会出现这种情况(有关更多详细信息,请参见下面的发布候选版本部分)。这意味着将跳过两个原本计划的发布(一个对应于第一个发布候选版本日期,一个对应于最终发布日期)。

预冻结阶段通常应在上一个稳定版本 X.Y.0 发布后 2 个月开始。

任何新版本系列的第一个预冻结版本始终为 X.Y.0a1(因为没有先前具有相同 ABI 版本标记的版本来判断二进制兼容性)。

预冻结版本会在其 C ABI 兼容性标记中获得一个额外的标志,以避免与最终的稳定版本发生二进制兼容性问题。

beta 版本的发布策略

本 PEP 建议将 beta 版本的策略设置为如下:

  • 与当前的 beta 版本一样,在准备和发布 beta 版本之前,稳定的 BuildBot 集群应处于绿色状态。
  • 与当前的 beta 版本一样,发布经理应在准备和发布 beta 版本之前审查开放的发布阻碍问题。
  • 与当前的 beta 版本一样,对 abi3 稳定 C ABI 的任何添加预计将成为该 ABI 的永久部分,除非并且直到该稳定 ABI 版本被完全弃用为止(注意:目前没有计划增加稳定 ABI 版本)。
  • 与当前的 beta 版本不同,本 PEP 中的 beta 版本不会被视为下一个 X.Y.0 版本的功能完整版本。
  • 与当前的 beta 版本不同,自上次 CPython 功能发布(除了对稳定 C ABI 的添加)以来添加的所有 API 都被视为临时 API。
  • 与当前的 beta 版本不同,本 PEP 中的 beta 版本将从主开发分支准备和发布。
  • 与当前的 alpha 或 beta 版本不同,本 PEP 中的 beta 版本需要与系列中的直接前一个预发布版本完全 ABI 兼容(不包括对临时 API 的任何更改,或删除在上一个发布系列中已弃用的 API)。

alpha 版本的发布策略

本 PEP 建议将 alpha 版本的策略设置为如下:

  • 与当前的 alpha 版本一样,在准备和发布 alpha 版本之前,稳定的 BuildBot 集群应处于绿色状态。
  • 与当前的 alpha 版本一样,发布经理应在准备和发布 beta 版本之前审查开放的发布阻碍问题。
  • 与当前的 alpha 版本不同,发布经理预计将针对与当前的 beta 版本类似的稳定性水平,即使对于 alpha 版本也是如此。

在本 PEP 中,只要无法发布满足 beta 版本标准的版本,并且在发布版本之前增加一些时间并不能解决问题,就会发布 alpha 版本。

预计 CPython API 的完全更改,会导致 ABI 兼容性问题(例如,可能在公共结构定义中添加或删除了字段)将是最有可能导致在发布初始兼容性标记定义 X.Y.0a1 版本以外的额外 alpha 版本的原因,但任何特定版本的决定都由发布经理做出。

候选版本策略、阶段持续时间和频率

鉴于对 alpha 和 beta 发布阶段的拟议更改,发布候选版本阶段将看到以下相关调整:

  • 功能冻结、ABI 冻结、pyc 文件格式冻结和维护分支创建都将与 X.Y.0rc1 的创建相对应(目前这些操作混合在 X.Y.0b1、最后一个 beta 版本和 X.Y.0rc1 中)。
  • X.Y.0 发布候选版本期间将从 3 周延长到 2 个月。
  • 通常会发布两个相隔一个月的发布候选版本,但发布经理可以酌情发布更多候选版本。
  • 最终的 X.Y.0 版本将在最终发布候选版本后 1 到 4 周内发布(取决于在第二个发布候选版本之后是否需要发布额外的发布候选版本)。
  • 如果最终的 X.Y.0 版本延迟超过 8 月的目标日期,则后续版本系列不受影响,并将仍然计划在 8 月发布(现在是 2 年后的时间)。

除了为最终用户提供更多时间来反馈发布候选版本,这种调整后的策略还为 Python 项目的维护者提供了更多时间来为新的稳定版本系列构建和发布预编译的 wheel 档案,从而显着提高了 X.Y.0 版本的初始用户体验。

CPython 稳定 C ABI 管理的变更

CPython 稳定 ABI [5] 承诺,针对任何特定 CPython 版本构建的二进制扩展模块将继续在支持相同稳定 ABI 版本的未来 CPython 版本上工作(该版本目前为 abi3)。

在提出的滚动预冻结发布模型中,该承诺将扩展到也适用于 beta 版本:一旦为即将发布的 Python 版本有意向 abi3 稳定 ABI 中添加的内容在 beta 版本中发布,那么只要 abi3 稳定 ABI 仍然受支持,它就不会从未来的版本中删除。

将提供两种主要机制来获取社区对稳定 ABI 添加内容的反馈。

  • 首选机制是先将新的 API 添加到 CPython API 中,然后在将它们添加到至少一个已发布的 beta 版本中并获得相关用户反馈后,再将它们提升到稳定 ABI。
  • 对于由于某些原因无法使用这种方法的 API(例如,某些 API 添加在 CPython API 可用时可能没有用处),开发人员可以要求发布经理将下一个版本标记为 alpha 版本(即使在 CPython API 中没有 ABI 破坏的情况下),并尝试通过这种方式获得进一步的反馈。

为了略微提高可读性和易用性,本 PEP 还建议引入每个主要稳定 ABI 版本的别名。

#define Py_LIMITED_API_3_3 0x03030000
#define Py_LIMITED_API_3_4 0x03040000
#define Py_LIMITED_API_3_5 0x03050000
#define Py_LIMITED_API_3_6 0x03060000
#define Py_LIMITED_API_3_7 0x03070000
#define Py_LIMITED_API_3_8 0x03080000
#define Py_LIMITED_API_3_9 0x03090000
// etc...

这些别名将在扩展模块代码中用于设置目标 ABI 版本。

#define Py_LIMITED_API Py_LIMITED_API_3_8

以及在 CPython 解释器实现中用于检查应该提供哪些符号。

#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= Py_LIMITED_API_3_9
// A Python 3.9+ addition to the stable ABI would appear here
#endif

滚动预冻结版本和稳定 C ABI 的文档将明确说明针对较晚的预冻结版本中的稳定 ABI 构建的扩展模块可能无法在较早的预冻结版本上正确加载。

alpha 版本和稳定 C ABI 的文档将明确说明,即使是在 alpha 版本中针对稳定 ABI 构建的扩展模块,如果连续发布两个 alpha 版本,也可能无法在下一个版本上正确加载(这种情况理想情况下应该是很少发生的)。

CPython 全 ABI 管理的变更

本 PEP 建议对 CPython 稳定 ABI 的管理进行两项更改。

用于标记 ABI 突破性变更的显式提交和 NEWS 文件约定

本 PEP 中的提案要求发布经理能够根据预冻结版本是否包含 ABI 破坏性更改,将其适当地标记为 alpha 版本或 beta 版本。

为了帮助完成此过程,将要求核心开发人员在所有 NEWS 文件片段中包含“(CPython ABI break)”标记,这些片段用于引入 CPython C ABI 中的破坏性更改。

包含“CPython”标记是为了明确这些注释与 CPython 稳定 ABI 相关,而不是与稳定 ABI 相关。

对于提交信息,较短的标记“(ABI break)”将被放在提交摘要行的开头。

合并前的机器人将被更新,以确保如果 ABI break 标记出现在两个位置之一,则它会出现在两个位置。

如果该标记不小心从初始提交信息和 NEWS 条目中省略,则应在将标记添加到 NEWS 条目的后续提交中包含提交信息标记。

除了对发布经理有用之外,这些标记对于开发人员在针对受影响的版本进行测试时调查意外的段错误也很有用。

显式标记针对预冻结 ABI 的构建

完整的 CPython ABI 长期以来一直遵循一项策略,即二进制兼容性仅在 ABI 宣布冻结后适用于发布系列内,而源代码兼容性仅适用于不同的发布系列。

此策略意味着针对 CPython 预发布版本(在该发布系列的 ABI 冻结之前)构建的扩展模块可能无法在最终版本上正确加载。

这是由于扩展模块可能依赖于在后续的 alpha 或 beta 版本中已更改或删除的临时或以前已弃用的接口,或者可能是由于扩展模块使用的公共结构由于添加了新字段而改变了大小。

从历史上看,alpha 和 beta 版本的采用率一直很低,以至于在实践中这并没有真正成为问题。但是,本 PEP 提出积极鼓励广泛地使用 beta 版本,这使得确保这些版本的使用者不会无意中发布导致运行发布候选版本和最终版本的使用者发生段错误的二进制扩展模块变得很有必要。

为此,本 PEP 提出修改非 Windows 系统上的扩展模块 SOABI 标记,以包括一个用于 CPython 预发布版本的新的“p”标志,并且仅在进入发布候选阶段时,该特定 X.Y.0 版本的 ABI 冻结后才切换回省略该标志。

通过此更改,3.9.0 的 alpha 和 beta 版本将获得 cpython-39p 的 SOABI 标记,而所有发布候选版本和最终构建版本(对于 3.9.0 和后续的 3.9.x 版本)将获得 cpython-39 的未限定 SOABI 标记。

调试构建仍然会在标记的末尾添加“d”,为预发布版本的调试构建提供 cpython-39pd

在 Windows 系统上,预发布构建中带标记的 pyd 文件的后缀将在版本号之后立即包含“p”作为预发布标记,从而给出类似“cp39p-win_amd64”的标记。

此更改的提议参考实现可在 [4] 中找到(注意:在撰写本文时,该实现尚未在 Windows 上测试)。

更新受全 C ABI 变更影响的项目的 Python-Requires

当项目首次选择为滚动预冻结发布系列提供预构建的二进制轮子时,他们无需执行任何特殊操作:他们会将滚动发布系列添加到他们的构建和测试矩阵中,并发布标记为与该发布系列兼容的二进制存档,就像他们在为该发布系列的完整 CPython ABI 冻结后提供预构建的二进制轮子一样。

但是,如果该项目受到滚动发布流中 CPython ABI 兼容性中断的影响,那么他们将需要发布一个版本更新,其中包含新的二进制构建和新的环境约束的 Python-Requires 标记。

例如,如果支持滚动发布流的项目在 3.9.0a5 版本中受到 CPython ABI 兼容性中断的影响,那么他们将在发布更新的二进制构建的版本上添加以下元数据条目

Python-Requires: >= "3.9.0b6"; python_version == "3.9" and full_python_version != "3.9.0a5"

这样做会作为已发布软件包的一部分添加额外的兼容性约束,因此早于 3.9.0b6 的 Python 3.9.0 beta 版本不会将更新的软件包视为安装候选,而唯一会考虑该软件包的 alpha 版本是 3.9.0a5 本身。

注意事项和局限性

实际发布日期可能会根据发布团队的可用性和其他事件(例如 PyCon US 或年度核心开发人员冲刺)的安排,由发布经理自行决定提前或延迟一个月。但是,由于提案的目标之一是提供一致的发布节奏,因此调整应该理想情况下很少见。

在发布系列内,维护版本的具体频率仍由发布经理和二进制发布团队决定;本 PEP 仅提出了预发布版本和 X.Y.0 版本的预期节奏。

但是,为了示例时间线的目的,PEP 假设每隔一个月发布一次维护版本,使它们能够与滚动预冻结版本交替发布。

发布经理和指导委员会还将保留修改本 PEP 中提案中各种细节的权力。可能的修改包括(但不限于)

  • 更改创建维护分支的时间。如果需要新 alpha 版本的重大更改在预发布过程的后期阶段被合并,发布经理可以选择从该重大更改之前的某个点进行分支。例如,如果下一次计划的发布版本打算作为最终的 beta 版本或第一个发布候选版本,这样做可能是有意义的。
  • 声明 alpha 版本的标准可以扩展到包括所有需要在“What’s New”文档中添加“Porting”条目的更改
  • 而不是根据需要声明 alpha 版本,发布经理可以提前声明一些日期为 alpha 版本,并要求核心开发人员相应地安排他们更高风险的更改。

PEP 中具体提案的目的是为审阅者提供一个清晰的说明性示例,而不是限制我们根据实践经验调整特定细节的能力。

设计讨论

为什么使用滚动预冻结版本而不是简单地更频繁地发布 X.Y.0 版本?

对于 Python 用户群体的很大一部分来说,新 CPython 功能版本的可用性并不是他们采用这些新版本的限制因素(这种影响在 PyPI 下载元数据等指标中可见)。

因此,任何基于加快完整功能版本发布的提案都需要在满足那些会尽快采用每个版本的用户的需求与那些现在处于每 2、3 或 4 个版本采用一次的位置的用户需求之间取得平衡,而不是能够在生命周期的某个时间点迁移到几乎每个版本。

本提案旨在通过定义一个新的生产就绪发布流来从不同的角度解决这个问题,该发布流更专门地针对能够像 CPython 核心团队准备生产新版本一样快地消费新版本的运行环境的兴趣。

是否有必要保留“alpha”和“beta”命名方案?

对提议的滚动发布使用“a”和“b”首字母是受 CPython 版本号发布方式的一些实际方面强加的设计约束。

具体来说,alpha 版本、beta 版本和发布候选版本在某些地方使用字符串“a”、“b”和“c”分别报告,而在其他地方使用十六进制数字 0xA0xB0xC 报告。我们希望保留这一点,同时还要确保任何 Python-Requires 约束都针对 beta 版本而不是 alpha 版本(因为如果连续发生两个 alpha 版本,后者可能无法强制执行 abi3 稳定性要求)。

但是,没有任何东西强迫我们说“a”代表“alpha”或“b”代表“beta”。

这意味着,如果我们想要提高那些只因“beta”标签而被推迟的人的采用率,那么强调“*A*BI break”和“*B*inary compatible”名称而不是“alpha”和“beta”名称可能是有意义的,从而得到

  • 3.9.0a1:ABI break 预冻结发布
  • 3.9.0b2:二进制兼容预冻结发布
  • 3.9.0rc1:发布候选版本
  • 3.9.0:最终发布

本 PEP 的这次迭代并没有走那么远,因为将滚动预冻结发布版本的初始采用限制在那些对“beta”标签感到舒适的人身上可能是一件好事,因为是这些版本的最早采用者会遇到在更广泛的 Python 生态系统层面上出现的任何意外后果,我们需要他们愿意积极参与解决这些问题。

如果最终的体验足够积极,以至于我们决定该方法值得继续,那么放弃“beta”命名将成为未来需要考虑的选择。

为什么使用滚动预冻结版本而不是在稳定和不稳定版本系列之间交替?

除了使用 beta 阶段进行滚动发布之外,另一个选择是在传统的稳定发布版本(例如 3.8.x、3.10.x 等)和使用新的滚动发布节奏的发布系列(例如 3.9.x、3.11.x 等)之间交替发布。

这个想法与 PEP 598PEP 602 存在相同核心问题:它对那些对现状感到满意的最终用户强加了更改,而没有为他们提供任何明确的补偿性益处。

它还受到针对 PEP 598 提出的主要担忧之一的影响:至少一些核心开发人员和最终用户强烈希望不要将任何特定的语义分配给发布版本中任何数字的。这些社区成员更倾向于将所有语义意义与正在更改的发布号码中的位置相关联。

相比之下,滚动预冻结发布提案旨在通过确保提议的策略更改都围绕着特定发布版本是 alpha 版本、beta 版本、发布候选版本还是最终版本来解决这个问题。

为什么不在滚动发布流中使用日历版本控制?

Steve Dower 在最初提出该提案时 [1] 建议对滚动发布流使用日历版本控制(因此,Python 3.8.0 之后的第一个滚动预发布版本将是 Python 2019.12 而不是 3.9.0b1)。

Paul Moore 指出 [2] 该提案的两个主要实际问题

  • 对于使用基于日历的版本的使用者来说,他们与传统编号的版本之间的关系并不明确
  • 它打破了打包工具中 Python-Requires 元数据处理,没有明确的方法可以可靠地修复它(因为所有日历版本看起来都比任何标准版本更新)

本 PEP 旨在通过对滚动发布使用已建立的 beta 版本号来解决这两个问题。

例如,考虑以下问题:“Python 2021.12 是否包含 Python 3.9.0 中发布的所有新功能?”。对于滚动发布上的日历版本控制,如果不参考发布日历查看 3.9.0rc1 是何时从滚动发布系列中分支出来的,这是不可能回答的。

相比之下,滚动预冻结发布的等效问题很容易回答:“Python 3.10.0b2 是否包含 Python 3.9.0 中发布的所有新功能?”。仅仅从问题本身,答案显然是“是的,除非它们是已删除的临时功能”。

beta 编号方法还避免了日历版本控制概念引发的其他问题,例如 sys.version_infoPY_VERSION_HEXsite-packages 目录命名以及已安装的 Python 二进制文件和扩展模块命名如何运作。

滚动预冻结版本的使用者如何检测 API 变更?

在添加新功能时,强烈建议核心开发人员支持功能检测和通过不依赖于 sys.version_info 或运行时代码对象内省的机制,优雅地回退到替代方法。

在大多数情况下,对受影响模块进行简单的 hasattr 检查将满足此目的,但如果不能,则会在添加功能时考虑替代方法。这方面的先例包括 pickle.HIGHEST_PROTOCOL 属性、hashlib.algorithms_available 集合以及 os 模块已经提供的各种 os.supports_* 集合,用于平台相关功能检测。

也可以添加需要通过 __future__ 导入显式启用才能在首次包含在滚动预冻结版本中才能使用的功能,即使该功能标志随后在 X.Y.0 发布候选版本首次出现之前默认启用也是如此。

这些方法背后的理由是,像这样显式检测/启用将使滚动预冻结发布流的用户能够轻松地注意到我们何时删除或更改临时功能(例如,from __future__ 导入如果功能标志不再存在,则在编译时会中断),或者安全地回退到以前的功能。

解释器丰富的属性查找机制意味着我们也可以选择对我们没有实际方法添加以检查 sys.version_info 值的临时或弃用导入和属性添加警告。

为什么在 X.Y.0rc1 之后添加一个新的预冻结 ABI 标志来强制重建?

核心开发团队目前积极 *不鼓励* 在 ABI 冻结日期之前为 X.Y 系列创建公共预构建二进制文件。

我们这样做的原因是,为了避免在稳定版 X.Y.0 版本上出现痛苦的调试会话的风险,这些调试会话可以追溯到“哦,我们的依赖项‘superfast-binary-operation’ 受 X.Y.0a3 中的 CPython ABI 中断的影响,但该项目自那时起尚未发布新的构建”。

有了拟议的预冻结 ABI 标志,发布采用流程的这一方面本质上与现状保持一致:新的 CPython X.Y 发布系列进入 ABI 冻结 -> 软件包维护人员发布该发布系列的新的二进制扩展模块 -> 最终用户只因实际的错误而出现段错误,而不是仅仅针对不兼容的 ABI 进行构建。

因此,新的预冻结 ABI 标志的主要目标是通过允许为这些版本发布预构建的二进制存档,而不会冒目前导致我们积极阻止发布二进制工件的那些问题的风险,来改善滚动预冻结版本本身的用户体验。

在理想情况下,软件包维护人员只需要在 X.Y.0a1 发布一次预冻结二进制构建,然后在 X.Y.0rc1 发布后发布一次冻结后构建。只有在项目实际受到介入的 Alpha 版本中的 CPython ABI 中断影响的情况下,才 *需要* 在此期间重建。

举个具体的例子,考虑以下场景:我们最终有三个包含 ABI 中断的版本:X.Y.0a1、X.Y.0a5、X.Y.0a7。然后,X.Y.0a7 ABI 是贯穿所有后续 Beta 版本以及 X.Y.0rc1 的 ABI。(这是图 1 中所示的场景)

迫使每个人在滚动发布流中每次发布 Alpha 版本时都重建整个世界,几乎肯定会导致发布者决定支持滚动发布会比其价值更大,因此我们希望允许针对 X.Y.0a1 构建的模块加载到 X.Y.0a7 中,因为它们 *可能* 会兼容(很少有项目使用 CPython 发布的每个 C API,并且大多数 ABI 中断都会影响一个特定的 API)。

但是,一旦我们发布 X.Y.0rc1,我们就希望确保针对 X.Y.0a1 和 X.Y.0a4 构建的任何二进制文件都完全从最终用户体验中删除。能够保留针对 X.Y.0a7 和任何后续 Beta 版本构建的版本(因为事实证明它们实际上是针对冻结后的 ABI 构建的,即使我们当时并不知道)会很好,但丢失它们不会比现状 *更糟糕*。

这意味着预冻结标志是解决此问题 *可能起作用的最简单方法* - 它只是一个新的 ABI 标志,并且我们已经拥有处理 ABI 标志的工具(在解释器以及软件包发布和安装工具中)。

由于 ABI 标志相对于预发布版本已发生更改,因此项目甚至不需要发布新版本:它们可以将新的 wheel 存档上传到其现有版本,就像他们今天可以做的那样。

能够追溯接受针对最后一个 Alpha 或后续 Beta 版本构建的所有内容的更巧妙的方案可能是可能的,但对于采用此 PEP 来说 *并不* 被认为是必要的,因为即使我们最初从一个简单的预发布 ABI 标志开始,仍然可以在将来设计出更复杂的方法。

为什么在 X.Y.0a1 之后允许额外的 alpha 版本?

在理想情况下,对完整 CPython ABI 的所有破坏性更改将与文件系统布局更改一起出现在 X.Y.0a1 中,并且该发布系列的 ABI 将在那之后保持稳定。

但是,最近的历史并没有表明我们能够真正做出这样的承诺并坚持下去,因此 PEP 假设 ABI 更改将在预冻结期间逐步进行,并且完整的锁定将仅在准备 X.Y.0rc1 时创建 X.Y.z 维护分支时发生。

对 CPython 核心开发的影响

对于 CPython 核心开发而言,主要变化是需要使主分支更一致地发布准备就绪。

虽然对此的主要要求是保持稳定的 BuildBot 集群处于绿色状态,但也鼓励将开发版本的文档保持最新,以使滚动预冻结版本的用户受益。这将包括为更改提供草稿“新增内容”条目,即使这些初始版本可能相对简略,然后根据 Beta 版本用户的反馈进行扩展。

对于在 CPython C API 上工作的核心开发人员,还需要一个新的要求,即始终在他们的 NEWS 文件片段中标记 ABI 中断更改。

关于稳定 ABI 的具体主题,大多数 API 设计将能够经历一个过程,首先将它们引入为完整 CPython API 的临时部分(允许在预冻结版本之间进行更改),并且只有在开发人员确信该接口真正稳定后才能将其提升到稳定 ABI。

只有在 API 在稳定 ABI 之外没有用处的极少数情况下,才可能发布包含临时稳定 ABI 添加的 Alpha 版本,而不是在临时 CPython API 中迭代设计。

对 Python 库开发的影响

如果此 PEP 成功实现了其目标,那么支持滚动预冻结发布流对于库作者而言应该不会比支持稳定版本更痛苦。

对于纯 Python 软件包的发布者来说,这将是发布“py3”标记的 wheel 存档,并可能在他们的测试矩阵中添加滚动预冻结发布流,如果他们有这个选项的话。

对于二进制扩展模块的发布者来说,首选的选项是针对稳定的 C ABI(如果可行),因此享受类似于纯 Python 软件包的体验,其中一个预构建的 wheel 存档能够涵盖多个版本的 Python,包括滚动预冻结发布流。

此选项并不适用于所有库,而这些作者的期望结果是他们能够通过构建和发布一个额外的 wheel 存档来支持滚动发布,该存档是针对初始 X.Y.0a1 版本构建的。然后,针对 X.Y.0rc1 或更高版本进行的后续构建与仅支持最终稳定版本所需的构建相同。

只有在特定库直接受到这两个时间点之间发生的任何其他 Alpha 版本中 ABI 中断影响的情况下,才需要额外的 wheel 构建。

提供滚动预冻结发布流也可能使更多 CI 提供商提供“CPython Beta 版本”测试选项变得更加可行。目前,此功能仅可从愿意并能够投入必要的时间和精力来创建、测试和发布自己的 CPython 主分支构建的 CI 提供商获得(例如 [6])。

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

根据在 SciPy 2019 上的讨论,已起草了 NEP(NumPy 增强提案)29 [3],以提出整个科学 Python 生态系统中放弃对旧版 Python 版本支持的通用约定。

虽然该策略的确切措辞仍在讨论中,但草案提案(截至 2019 年 10 月 20 日)建议项目支持过去 42 个月内发布的任何 Python 功能版本,至少支持最新的 2 个 Python 功能版本。

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

对于 12 个月的版本发布节奏,它将始终至少支持三个最新的功能版本,然后在 X.(Y+3).0 发布大约 6 个月后,放弃对所有 X.Y.Z 版本的支持。这意味着在每年的半年时间里,将支持四个最新的功能版本,而每年的另一半年时间将用于为当年的功能版本发布做好准备。

对于 24 个月的版本发布节奏,第二条条款优先于第一条条款,并且建议的 Python 版本支持期限从初始 X.Y.0 版本开始增加到 48 个月,以便始终支持两个最新的 CPython 功能版本。对于还支持滚动发布流的项目,支持的功能版本数量将增加到三个。

核心开发冲刺的发布周期对齐

有了此 PEP 中的提案,预计核心开发冲刺的重点将根据当前在两年周期中的位置略微转移。

在发布年份,PyCon US 的时间安排适合新贡献者在第一个发布候选版本发布之前处理错误修复和小功能,而语言峰会和核心开发人员讨论可以集中在下一发布系列的计划上。

发布年份的 Alpha 之前核心开发冲刺将提供一个机会来整合对先前版本的反馈,无论是作为下一个维护版本的组成部分(对于错误修复和对临时 API 的反馈),还是作为下一个发布系列的第一个 Alpha 版本的组成部分(对于对稳定 API 的反馈)。

这些初始 Alpha 版本也将是针对完整 CPython ABI 的 ABI 中断更改的首选目标(虽然发布周期中后期的更改仍然允许,如本 PEP 中所述,但在 X.Y.0a1 版本中将它们合并意味着它们不会为预构建二进制软件包的发布者触发任何额外的工作)。

下一发布周期的指导委员会选举也可能与 Alpha 之前开发冲刺同时进行。

在非发布年份,这两个事件的重点都将集中在即将到来的维护和预冻结版本上。这些不那么紧张的年份有望提供一个机会来解决各种流程更改和基础设施升级,而不会影响发布候选版本准备流程。

主要 Linux 发行版的发布周期对齐

一些滚动发布的 Linux 发行版(例如 Arch、Gentoo)可能能够使用本 PEP 中提出的新的滚动冻结前版本,但预计大多数发行版将继续使用已建立的版本。

本 PEP 中提出的最终版本的具体日期选择与 Ubuntu 和 Fedora Linux 发行版每年 10 月发布的年度功能冻结时间表相一致。

对于 Fedora 和 Ubuntu 来说,这意味着发布候选阶段与发行版开发周期相一致,这是它们测试新版本并提供有关潜在回归和兼容性问题的反馈的理想时间。

对于 Ubuntu 来说,这也意味着它们的 4 月 LTS 版本将受益于使用新的系统 Python 版本的完整的短期发布周期,同时该 CPython 版本仍然可以针对大多数时间(直到下一个 Ubuntu LTS 版本发布)的 upstream 错误修复保持开放。

与本 PEP 中的具体提案可能始终不一致的唯一 Linux 发布周期对齐是 Debian,因为自 2005 年以来,Debian 一直在奇数年上半年的发布(与 Ubuntu LTS 版本大致相差 12 个月)。

随着 PEP 602 中的年度发布提案,Debian 和 Ubuntu LTS 将始终获得一个大约 6 个月旧的系统 Python 版本,但也会始终选择彼此不同的 Python 版本。

以两年为周期,CPython 版本在一年下半年发布,它们可能会选择彼此相同的版本,但其中一个会选择一个 CPython 版本,该版本在 Linux 发行版发布时距离最新 beta 版本超过 18 个月。

如果这种情况真的发生,并且被认为不可取(但对于 *Debian* 来说,选择调整其发布时间并不足够不可取),那么这就是 PEP 598 中的“增量功能发布”提案的额外复杂性可能证明其价值的地方。

(将 CPython 版本移动到与 Debian 和 Ubuntu LTS 版本相同的一年半将有可能帮助缓解这个问题,但也带来了新的问题:CPython 版本计划的偏差可能会直接影响 Linux 发行版的版本计划,或者导致发行版发布一个 Python 版本,该版本比 18 个月旧 *更多*)

对简单部署环境的影响

对于本 PEP 的目的来说,“简单”部署环境是指任何用例,其中确保所有目标环境同时更新到新的 Python 版本(或至少在新的更高层应用程序版本推出之前)是直接的,并且发生的任何预发布测试只需要针对单个 Python 微版本。

最简单的案例将是个人使用的脚本,其中测试环境和目标环境完全相同。

类似的简单环境将是容器化 Web 服务,其中 CI 管道中使用与部署中相同的 Python 容器,以及任何将自己的 Python 运行时捆绑在一起的应用程序,而不是依赖于目标系统上的预先存在的 Python 部署。

对于这些用例,存在一个简单的机制来最大程度地减少本 PEP 的影响:继续使用稳定版本,并忽略滚动冻结前版本。

为了在这些环境中实际采用滚动冻结前版本,主要挑战将是处理在下一个冻结前版本是 alpha 版本而不是 beta 版本时,扩展模块段错误的可能性,这表明 CPython ABI 可能以不兼容的方式发生了改变。

如果所有使用的扩展模块都针对稳定 ABI,那么就不会有任何问题,一切都将像在稳定版本上一样顺利地工作。

或者,“重新构建并重新缓存所有扩展模块”可以成为在更新到 alpha 版本时进行的标准活动。

最后,也合理的是,直到实际出现问题才担心它,然后像处理新的 alpha 或 beta 版本中发现的任何其他库兼容性问题一样进行处理。

除了扩展模块 ABI 兼容性之外,使用滚动冻结前版本时,另一个主要的额外复杂性是“回滚”兼容性,用于独立版本的功能,例如 pickle 和 SQLite,其中在 beta 流中使用新功能或临时功能可能会创建稳定版本无法读取的文件。使用这些类型功能并且还需要能够可靠地回滚到以前的稳定 CPython 版本的应用程序,建议如今天一样避免采用预发布版本。

对复杂部署环境的影响

为了本 PEP 的目的,“复杂”部署环境是指不满足上述“简单部署”标准的用例。它们可能涉及多个不同的 Python 版本,使用个性化的 Python 版本,或者需要“守门人”在部署之前批准使用新版本的用例。

例如,作为标准操作系统环境的一部分在用户机器上安装 Python 的组织属于此类别,提供标准构建环境的组织也是如此。提供一致构建和验证的软件包集合的发行版(如 conda-forge 或 WinPython)受到类似的影响。

这些组织往往要么偏爱高稳定性(例如,所有那些愉快地使用稳定 Linux 发行版(如 Debian、RHEL/CentOS 或 Ubuntu LTS)中的系统 Python 作为其首选 Python 环境的人),要么偏爱快速周转(例如,那些定期为最新的 CPython 预发布版本做出贡献的人)。

在某些情况下,两种使用模式可能在同一个组织中以不同的目的存在,例如

  • 为关键任务系统使用稳定的 Python 环境,但允许数据科学家使用最新版本进行临时数据分析
  • 硬件制造商将其生产固件的一部分部署为稳定的 Python 版本,但在其自动集成测试的开发和执行中使用最新版本

在任何发布模型下,Python 的每个新版本都会为这些组织生成工作。这项工作可能包括对 Python 本身进行法律、安全或技术审查,评估和验证有影响的变化,重新应用补丁,重新编译和测试第三方依赖项,然后才是部署。

能够快速更新的组织应该能够利用更频繁的 beta 版本。虽然每次更新仍然需要类似于他们今天所需要的调查工作,但每次发布所需的工作量应该会减少,因为每次发布与之前的发布相比将更加相似。拟议的每两个月发布一次模型的一个优点是,组织可以选择自己的采用节奏,从采用每个 beta 版本到每个季度采用一个,或每 6 个月采用一个,或每年采用一个。除此之外,继续使用稳定版本可能更有意义。

对于评估更严格或偏爱稳定性的组织来说,稳定版本的更长发布周期将减少更新所需的年度工作量,更长的发布候选周期将允许更多时间在 X.Y.0 版本发布之前进行内部测试,并且更多人在 beta 期间的使用将为初始版本提供更大的信心。同时,该组织可以放心地通过维护版本进行升级,而无需担心发生重大更改。

致谢

感谢 Łukasz Langa 创建了 PEP 602 并推动了对 CPython 发布节奏的可能改进的讨论,并感谢 Kyle Stanley 和 h-vetinari 对本 PEP 初稿的建设性反馈。

参考文献


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

上次修改:2023-10-11 12:05:51 GMT