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

Python 增强提案

PEP 413 – 更快地演进 Python 标准库

作者:
Alyssa Coghlan <ncoghlan at gmail.com>
状态:
已撤回
类型:
流程
创建日期:
2012年2月24日
发布历史:
2012年2月24日,2012年2月25日

目录

PEP 撤回

随着 PEP 453 被接受,意味着 pip 将默认提供给大多数新的 Python 用户,这有望减轻在模块尚未足够成熟之前就将其添加到标准库的压力。

过去几年,标准库包与 Python 包索引(PyPI)中支持旧版本 Python 的等效包同时存在的模型使用率也越来越高。

鉴于这两个发展以及在 Python 3.4 发布周期中的参与度,PEP 作者认为现在不再适合对标准库的开发流程进行如此根本性的改变。

摘要

本 PEP 提议采用一种独立的标准库版本控制方案(独立于现有语言版本控制方案,但与之关联),该方案允许 Python 标准库加速发布,同时保持(甚至放缓)核心语言定义当前的变化速度。

PEP 407 类似,它旨在调整当前在衡量变化(允许更广泛的社区有时间适应)和跟上比当前发布周期更能快速处理的外部影响(尤其是与 Web 技术相关的标准库元素)之间的平衡。

然而,它在目标上比 PEP 407 更保守,寻求将开发速度的加快限制在内置和标准库接口上,而不影响其他元素的变化速度,例如语言语法、版本编号以及 CPython 二进制 API 和字节码格式。

基本原理

引用 PEP 407 的摘要:

为开源项目找到发布周期是一个精妙的练习,需要管理相互矛盾的约束:开发者人力、发布管理志愿者的可用性、用户和第三方打包者的维护便利性、新功能(和行为变更)的快速可用性、在不引入新功能或行为变更的情况下获取错误修复的可用性。

当前的发布周期倾向于保守。它适合那些重视稳定性而非响应能力的人。本 PEP 试图在保持 Python 标志性的稳定性同时,通过引入长期支持版本(LTS)的概念,提供更流畅的功能发布。

我同意 PEP 407 作者的观点,即当前标准库的发布周期太慢,无法有效应对某些关键编程领域(特别是 Web 协议和相关技术,包括数据库、模板和序列化格式)的变化速度。

但是,我写了这份竞争性的 PEP,因为我相信 PEP 407 中提出的每 6 个月发布一次完全、可能不兼容二进制的 CPython 的方法,给更广泛的 Python 生态系统带来了过大的负担。

在当前的 CPython 发布周期下,关键二进制扩展的发行商通常会支持 Python 版本,即使 CPython 的分支已经进入“仅限安全修复”模式(例如,Twisted 目前提供 2.5、2.6 和 2.7 的二进制版本,NumPy 和 SciPy 支持这三个版本以及 3.1 和 3.2,PyGame 添加了 2.4 的二进制版本,wxPython 为 2.6 和 2.7 提供 32 位和 64 位二进制版本等)。

如果 CPython 的发布速度增加两倍(或更多),这些库的开发者(其中许多比 CPython 的资源更紧张)将面临一个令人不快的选择:要么自己采用更快的发布周期(PyGame 可能需要多达 18 个并发二进制版本!),要么更快地放弃旧的 Python 版本,或者告诉用户坚持使用 CPython LTS 版本(这样一来就完全失去了加快 CPython 发布周期的初衷)。

同样,许多 Python 的支持工具(例如语法高亮器)可能需要很长时间才能跟上语言级别的变化。

在文化层面,Python 社区也习惯了 Python 版本号的特定含义——它们与弃用周期、支持周期等各种事物相关联。PEP 407 提议将所有集体知识一扫而空,而没有提供有说服力的理由说明为什么这种行动是真正必要的(除了也许让 CPython 核心开发者的生活稍微轻松一些,而牺牲了其他所有人)。

然而,如果我们回到加快变化速度的主要原因(即更及时地支持 Web 协议和相关技术),我们可以注意到这些只需要标准库的更改。这意味着许多(甚至可能是大多数)对更广泛社区的负面影响可以通过明确限制 CPython 的哪些部分受新发布周期的影响,并允许其他部分以当前更平稳的速度发展来避免。

提案

本 PEP 提议引入一种新的 CPython 发布类型:“标准库发布”。与 PEP 407 一样,这将使 CPython 拥有 3 种发布类型:

  • 语言发布:“x.y.0”
  • 维护发布:“x.y.z”(其中 z > 0)
  • 标准库发布:“x.y (xy.z)”(其中 z > 0)

在此方案下,一个不加限定的版本引用(例如“3.3”)将始终指向最新的相应语言或维护版本。它绝不会被不加限定地用来指代标准库发布(至少,python-dev 不会这样做——显然,我们只能树立榜样,而不能强迫 Python 生态系统的其余部分遵循)。

语言发布将继续像现在一样,作为 Python 语言定义的新版本,以及 CPython 解释器和 Python 标准库的新版本。因此,语言发布可能包含以下任何或所有更改:

  • 新的语言语法
  • 新的标准库更改(见下文)
  • 新的弃用警告
  • 移除先前已弃用的功能
  • 发出的字节码的更改
  • AST 的更改
  • 编译工具链的任何其他重大更改
  • 核心解释器 eval 循环的更改
  • C ABI 的二进制不兼容更改(尽管 PEP 384 稳定 ABI 仍须保留)
  • 错误修复

维护发布也将继续像今天一样,严格限制为相应语言版本的错误修复。不允许有新功能或重大的内部更改。

新的标准库发布将与每个维护发布并行进行,并将用新的版本标识符来限定,以记录标准库的版本。标准库发布可能包括以下更改:

  • 纯 Python 模块中的新功能
  • C 扩展模块中的新功能(受 PEP 399 兼容性要求约束)
  • 语言内置函数中的新功能(前提是 C ABI 保持不变)
  • 相应维护版本的错误修复

标准库版本标识符是通过将 Python 语言发布的major和minor版本号组合成一个两位数,然后附加一个顺序的标准库版本标识符来构建的。

发布周期

当创建维护版本时,将在 python.org 上实际发布两个新的 Python 版本(以 2013 年 2 月计划的第一个 3.3 维护版本为例):

3.3.1       # Maintenance release
3.3 (33.1)  # Standard library release

又过了 6 个月,下一个 3.3 维护版本将再次伴随新的标准库发布。

3.3.2       # Maintenance release
3.3 (33.2)  # Standard library release

同样,标准库发布将与之前的语言发布二进制兼容,仅在 Python 层面提供额外功能。

最后,在 3.3 发布 18 个月后,一个新的语言版本将与最终的 3.3 维护和标准库发布大致在同一时间发布。

3.3.3       # Maintenance release
3.3 (33.3)  # Standard library release
3.4.0       # Language release

3.4 的发布周期随后将遵循与 3.3 类似的模式。

3.4.1       # Maintenance release
3.4 (34.1)  # Standard library release

3.4.2       # Maintenance release
3.4 (34.2)  # Standard library release

3.4.3       # Maintenance release
3.4 (34.3)  # Standard library release
3.5.0       # Language release

程序化版本标识

为了以编程方式暴露新的版本详细信息,本 PEP 提议添加一个新的 sys.stdlib_info 属性,该属性记录了标准库版本高于底层解释器版本的信息。以最初的 Python 3.3 版本为例:

sys.stdlib_info(python=33, version=0, releaselevel='final', serial=0)

这些信息也将包含在 sys.version 字符串中。

Python 3.3.0 (33.0, default, Feb 17 2012, 23:03:41)
[GCC 4.6.1]

安全修复和其他“周期外”发布

对于维护版本,处理周期外发布(例如,修复安全问题或解决新版本的关键错误)的流程与现在相同:递增次要版本号,然后发布一个包含所需错误修复以及自上一版本以来已提交的任何其他错误修复的新版本。

对于标准库发布,流程基本相同,但相应的“有什么新内容?”文档可能需要进行一些整理(因为标准库发布可能包含新功能,而不仅仅是错误修复)。

用户场景

上面提出的版本控制方案是基于如果采用该方案可能会遇到的多个用户场景。在每种情况下,场景都针对现状(即缓慢的发布周期)、本 PEP 中的版本控制方案以及 PEP 407 中提出的自由的次要版本号方案进行了描述。

为了给出结局,使用单独版本号的要点是,对于几乎所有场景,重要的数字是语言版本,而不是标准库版本。大多数用户甚至不需要关心标准库版本号的存在。在确定了需要它的两个场景中,将其作为一个单独的数字提供实际上比将两种不同类型的数字嵌入到单个序列中,然后将该统一序列中的某些数字标记为特殊数字更清晰、更明确。

新手用户,2013年3月从python.org下载Python

现状:必须在 3.3 和 2.7 之间选择

本 PEP:必须在 3.3 (33.1)、3.3 和 2.7 之间选择。

PEP 407:必须在 3.4、3.3 (LTS) 和 2.7 之间选择。

结论:解释长期支持版本的含义与解释拟议的标准库版本号的含义一样复杂。我称之为平局。

新手用户,尝试判断第三方文档的更新程度

现状:次要版本差异表示 18-24 个月的语言演进

本 PEP:语言核心与现状相同,标准库版本号表示 6 个月的标准库演进。

PEP 407:次要版本差异表示 18-24 个月的语言演进,直到 3.3,此后为 6 个月的语言演进。

结论:由于语言变更和弃用对第三方文档的准确性可能比为标准库添加新功能产生更大的影响,我将此称为本 PEP 方案的胜利。

新手用户,寻找扩展模块的二进制发布

现状:查找与正在运行的 Python 版本相对应的二进制文件。

本 PEP:与现状相同。

PEP 407 (完整发布):与现状相同,但相应的二进制版本更有可能缺失(或者,如果存在,则必须在更多的替代选项中找到)。

PEP 407 (ABI 更新仅限于 LTS 版本):所有二进制发布页面都需要告诉用户 Python 3.3、3.4 和 3.5 都需要 3.3 的二进制文件。

结论:我称之为本 PEP 方案的明显胜利。与当前情况相比,没有任何变化,因为在这种情况下,标准库版本实际上是无关紧要的(只有二进制扩展兼容性才重要)。

扩展模块作者,决定是否发布二进制版本

现状:除非使用 PEP 384 稳定 ABI,否则每次次要版本号更改时都需要新的二进制版本。

本 PEP:与现状相同。

PEP 407 (完整发布):与现状相同,但发生的频率要高得多。

PEP 407 (ABI 更新仅限于 LTS 版本):在做出决定之前,必须首先查找新版本是 LTS 版本还是临时版本。如果是 LTS 版本,则需要新的构建。

结论:我称之为本 PEP 方案的又一明显胜利。与此问题的面向终端用户的一面一样,在这种情况下,标准库版本实际上是无关紧要的。将该信息移到一个单独的数字中可以避免不必要的混淆。

Python 开发者,决定消除弃用警告的优先级

现状:触发弃用警告的代码不能保证在次要版本号更高的 Python 版本上运行。

本 PEP:与现状相同。

PEP 407:不明确,因为 PEP 目前没有详细说明。假设弃用周期与 LTS 版本相关联,那么升级到非 LTS 版本是安全的,但升级到下一个 LTS 版本可能需要避免已弃用的构造。

结论:本 PEP 方案的又一个明显胜利,因为在这种情况下,标准库版本再次无关紧要。

替代解释器实现者,更新新功能

现状:新 Python 版本 infrequent 地发布,但它们是标准库更新、核心语言定义和解释器更改的混合体。

本 PEP:标准库更新更容易集成,并且以一种清晰明确地与先前语言版本兼容的形式更频繁地提供。这意味着,一旦替代实现赶上 Python 3.3,它们在整合标准库功能方面应该会更容易(尤其是纯 Python 更改),只留下次要版本号更新作为需要更新其核心编译和执行组件的唯一任务。

PEP 407 (完整发布):与现状相同,但发生的频率要高得多。

PEP 407 (语言更新仅限于 LTS 版本):不明确,因为 PEP 目前没有详细说明具体的发展策略。假设采用了 3.3 兼容分支(如本 PEP 所建议),那么结果将大致相同,但版本号信号的清晰度会稍差一些(因为您需要检查特定版本是否为 LTS 版本)。

结论:虽然不如之前的一些场景那样清晰,但我仍然认为本 PEP 方案占优。显式优于隐式,本 PEP 方案在两种不同类型的更新之间进行了清晰的区分,而不是在普通版本号上添加单独的“LTS”标签。标记特定版本为特殊版本对于与版本控制系统和相关自动化工具进行通信非常有用,但对于向其他人类传达信息则是一个糟糕的方式。

Python 开发者,决定其最低版本依赖

现状:查找文档中的“版本添加”或“版本更改”标记,与 sys.version_info 进行对比。

本 PEP:查找文档中的“版本添加”或“版本更改”标记。如果写成裸 Python 版本,例如“3.3”,则与 sys.version_info 进行对比。如果带有标准库版本限定,例如“3.3 (33.1)”,则与 sys.stdlib_info 进行对比。

PEP 407:与现状相同。

结论:本 PEP 中的方案实际上允许第三方库更明确地说明其采用标准库功能的速率。更保守的项目可能会将其依赖项固定到语言版本,并避免在标准库版本中添加的功能。移动速度更快的项目可以改为声明其对特定标准库版本的依赖。然而,由于 PEP 407 确实具有保留现状的优势,因此我将此判给 PEP 407(尽管优势微弱)。

Python 开发者,尝试重现追踪器中的问题

现状:如果尚未提供,请询问报告者他们正在使用哪个版本的 Python。这通常通过询问交互式提示的前两行显示的内容或 sys.version 的值来完成。

本 PEP:与现状相同(因为 sys.version 将更新为包含标准库版本),但可能需要更多次(用户知道足够的信息来声明其 Python 版本,但这不足以重现故障)。

PEP 407:与现状相同。

结论:又一个 PEP 407 的小幅优势。新的标准库版本用户在报告 Python 库(或 Python 本身,在我们自己的跟踪器上)的问题时可能需要提供给开发者的额外信息。然而,通过将其包含在 sys.version 中,许多故障报告将已经包含它,并且如果需要,很容易请求。

CPython 发布管理者,处理安全修复

现状:创建一个包含安全修复和源代码控制中任何其他错误修复的新维护版本。还为仅用于安全修复的分支创建源代码版本。

本 PEP:对于维护分支,与现状相同。还创建一个新的标准库版本(可能包含新功能和安全修复)。对于安全分支,为前一个维护分支和标准库更新分支创建源代码版本。

PEP 407:对于维护和安全分支,与现状相同,但处理非 LTS 版本的安全修复目前是一个开放性问题。

结论:PEP 407 更新以实际解决此场景之前,本 PEP 明显占优。

影响

对开发周期的影响

PEP 407 类似,本 PEP 将把新功能的交付分解成更离散的块。语言发布中不会一次性出现大量更改,而是每次语言发布将仅限于 6 个月的标准库更改,以及与新语法相关的任何更改。

对工作流程的影响

本 PEP 提议在正常工作流程中使用一个额外的分支。在 3.3 发布后,将使用以下分支:

2.7         # Maintenance branch, no change
3.3         # Maintenance branch, as for 3.2
3.3-compat  # New branch, backwards compatible changes
default     # Language changes, standard library updates that depend on them

在处理新功能时,开发人员需要决定它是否是标准库发布的可接受更改。如果是,则应将其签入 3.3-compat,然后合并到 default。否则,应直接签入 default

对在 3.3-compat 分支上进行的任何更改的“版本添加”和“版本更改”标记都需要用语言版本和标准库版本进行标记。例如:“3.3 (33.1)”。

直接在 default 分支上进行的任何更改都将像往常一样仅标记为“3.4”。

3.3-compat 分支正常开发将在 3.3 维护分支关闭时同时关闭。 3.3-compat 分支将保持开放状态以进行安全修复,其时间与 3.3 维护分支相同。

对错误修复周期的影响

错误修复工作流程的影响与新功能工作流程的影响基本相同——在更改到达 default 分支之前,还有一个额外的分支需要通过。

如果在维护版本中发现关键错误,那么将创建新的维护和标准库版本来解决问题。版本号的最后一部分将为语言版本和标准库版本递增。

如果在不影响相关维护版本的情况下在标准库版本中发现关键错误,那么将只创建一个新的标准库版本,并且只递增标准库的版本号。

请注意,在这些情况下,标准库发布可能包含其他功能,而不仅仅是错误修复。假设任何只关心接收错误修复而不混合新功能的人都已经严格依赖维护版本,而不是使用新的标准库版本。

对社区的影响

PEP 407 在社区影响方面有以下说法:

重视稳定性的人只需同步 LTS 版本,根据拟议的数字,这将提供相似的支持周期(在持续时间和稳定性方面)。

我认为这个说法简直是错的。生活并非如此简单。相反,第三方模块和框架的开发者将面临支持新发布周期完整速度的二进制更新的压力,教师和书籍作者将收到关于他们只涵盖“旧”版本 Python 的投诉(“你只用 3.3,最新的是 3.5!”),等等。

随着次要版本号开始比过去快 3 倍,我认为语言稳定性的看法也会下降(无论这些观点是否合理)。

我认为将加快变化速度的范围限定在标准库,并用单独的版本号明确区分它,将极大地让社区的其余部分放心,不,我们没有突然要求他们将自己的开发速度提高两倍。相反,我们只会以 6 个月一次的增量发布下一个语言版本的标准库更新,而不是将它们推迟到下一个语言定义更新,即使是那些与先前发布的 Python 版本向后兼容的更改。

PEP 407 中列出的社区好处同样适用于本 PEP,至少在标准库方面是如此:

重视响应能力和新功能可用性(而不必承担安装 alpha 版本或 Mercurial 快照的风险)的人,将比目前从新发布周期中获得更多价值。

想要贡献新功能或改进的人,将会更有动力去做,因为知道他们的贡献将更快地提供给普通用户。

如果更快的发布周期鼓励更多人专注于为标准库做贡献,而不是提出语言定义更改,我不认为这是一件坏事。

新闻更新的处理

有什么新内容?

“有什么新内容?”文档将被拆分成标准库发布和语言发布。因此,在 3.3 发布周期中,我们将看到:

  • Python 3.3 有什么新内容?
  • Python 标准库 33.1 有什么新内容?
  • Python 标准库 33.2 有什么新内容?
  • Python 标准库 33.3 有什么新内容?

最后,我们将看到下一个语言版本:

  • Python 3.4 有什么新内容?

为了方便忽略标准库发布的用户的利益,3.4 的“有什么新内容?”将链接回 3.3 系列的标准库发布的“有什么新内容?”文档。

NEWS

NEWS 文件的合并冲突已经是件麻烦事了。由于本 PEP 提议在正常工作流程中引入额外的分支,解决这个问题变得更加重要。虽然 Mercurial 的 phases 在一定程度上可能有所帮助,但最好能完全消除这个问题。

Barry Warsaw 的一个建议是采用一种不冲突的、每个更改对应一个文件的做法,类似于 Twisted 的做法 [2]

鉴于 3.3.0 版本将使用当前手动更新的 NEWS 文件,这种方法的一种可能布局如下:

Misc/
  NEWS  # Now autogenerated from news_entries
  news_entries/
    3.3/
      NEWS # Original 3.3 NEWS file
      maint.1/ # Maintenance branch changes
        core/
          <news entries>
        builtins/
          <news entries>
        extensions/
          <news entries>
        library/
          <news entries>
        documentation/
          <news entries>
        tests/
          <news entries>
      compat.1/ # Compatibility branch changes
        builtins/
          <news entries>
        extensions/
          <news entries>
        library/
          <news entries>
        documentation/
          <news entries>
        tests/
          <news entries>
      # Add maint.2, compat.2 etc as releases are made
    3.4/
      core/
        <news entries>
      builtins/
        <news entries>
      extensions/
        <news entries>
      library/
        <news entries>
      documentation/
        <news entries>
      tests/
        <news entries>
      # Add maint.1, compat.1 etc as releases are made

将版本信息放在目录层次结构中并非严格必要(因为 NEWS 文件生成器可以从版本历史中获取),但确实使得人类更容易保持不同版本的顺序。

减少版本耦合的其他好处

放慢语言发布周期

当前的发布周期是在核心语言定义和 C 扩展 ABI 的稳定性需求,以及希望更快地将新功能(尤其是标准库更新)交付给用户的手中之间的折衷。

通过(在一定程度上)将标准库发布周期与核心语言定义发布周期脱钩,它提供了一个机会来实际放慢语言定义的变更速度。Python 3.2 的语言冻结期实际上将该周期放慢到了三年多(3.1:2009 年 6 月,3.3:2012 年 8 月),而没有引起任何重大问题或抱怨。

上述 NEWS 文件管理方案实际上是为了让我们在标准库发布变得更频繁的同时,能够灵活地放慢语言发布的节奏。

作为简单示例,如果在 3.3 和 3.4 之间允许整整两年,3.3 的发布周期将如下所示:

3.2.4       # Maintenance release
3.3.0       # Language release

3.3.1       # Maintenance release
3.3 (33.1)  # Standard library release

3.3.2       # Maintenance release
3.3 (33.2)  # Standard library release

3.3.3       # Maintenance release
3.3 (33.3)  # Standard library release

3.3.4       # Maintenance release
3.3 (33.4)  # Standard library release
3.4.0       # Language release

拟议分支结构和 NEWS 条目布局的优雅之处在于,这个决定实际上直到 3.4 计划发布日期前不久才需要做出。届时,可以决定推迟 3.4 的发布,并在 3.3.3 维护版本和 3.3 (33.3) 标准库发布后继续开放 3.33.3-compat 分支,从而在该周期中添加另一个标准库发布。之后每 6 个月将提供另一个标准库发布或完整语言发布的选项。

进一步加快标准库开发的速度

如前一节所述,本 PEP 提出的方案的一个好处是它在很大程度上将语言发布周期与标准库发布周期分离。标准库可以每 3 个月更新一次,甚至每月更新一次,而不会对语言版本号或核心语言的感知稳定性产生任何后续影响。

虽然只要 Windows 和 Mac OS X 的二进制安装程序创建涉及多个手动步骤(包括手动测试),并且我们还没有独立的“<branch>-release”树来接收已由稳定 buildbots 标记为良好的版本,这种开发速度就不切实际,但它仍然是一个在考虑提议的新版本控制方案时应牢记的标准:如果我们最终希望使标准库发布比每 6 个月更快怎么办?

如果这些实际问题得到解决,那么本 PEP 中的独立标准库版本控制方案就可以处理。PEP 407 中提出的带标记版本号的方法则不能(至少,没有很多用户混淆和不确定性的话)。

其他问题

为什么不使用主版本号?

最简单和最合乎逻辑的解决方案实际上是将 major.minor.micro 版本号映射到语言版本、stdlib 版本和维护版本。

与其发布 Python 3.3.0,不如发布 Python 4.0.0,发布周期如下:

4.0.0  # Language release

4.0.1  # Maintenance release
4.1.0  # Standard library release

4.0.2  # Maintenance release
4.2.0  # Standard library release

4.0.3  # Maintenance release
4.3.0  # Standard library release
5.0.0  # Language release

然而,Python 2 -> Python 3 过渡的持续痛苦(以及诸如 python3python2 符号链接以直接指向所需的发布系列等变通方法)意味着出于历史原因,这个简单的选项是不可行的。

这个简单方法可以奏效的一种方式是,将当前的 major 和 minor 版本号直接合并为一个两位数的 major 版本号:

33.0.0  # Language release

33.0.1  # Maintenance release
33.1.0  # Standard library release

33.0.2  # Maintenance release
33.2.0  # Standard library release

33.0.3  # Maintenance release
33.3.0  # Standard library release
34.0.0  # Language release

为什么不使用四位版本号?

另一个简单的版本控制方案只是在现有版本控制方案中添加一个“标准库”版本:

3.3.0.0  # Language release

3.3.0.1  # Maintenance release
3.3.1.0  # Standard library release

3.3.0.2  # Maintenance release
3.3.2.0  # Standard library release

3.3.0.3  # Maintenance release
3.3.3.0  # Standard library release
3.4.0.0  # Language release

但是,由于 sys.version_info 结构的向后兼容性限制,该方案不可行。

为什么不使用基于日期的版本控制方案?

本 PEP 的早期版本提出了一个用于标准库的基于日期的版本控制方案。然而,这种方案使得处理周期外发布以修复标准库版本中的安全问题和其他关键错误非常困难,因为它需要以下步骤:

  1. 将发布版本号更改为当前月份的日期。
  2. 更新“有什么新内容?”、NEWS 和文档以引用新发布号。
  3. 进行新发布。

对于现在提出的顺序方案,此类发布最多只需要整理一下“有什么新内容?”文档,然后进行发布。

为什么 PEP 384 足够用?

PEP 384 引入了 CPython 的“稳定 ABI”概念,这是完整 C ABI 的一个有限子集,保证保持稳定。使用稳定 ABI 构建的扩展应该能够支持所有后续的 Python 版本,且二进制文件相同。

这将有助于新项目避免将其 C 扩展模块与特定 CPython 版本过于紧密地耦合。但是,对于现有模块,迁移到稳定 ABI 可能涉及大量工作(特别是对于定义了大量类的扩展模块)。由于可用的开发资源有限,任何花费在此类更改上的时间都可以用于开发为最终用户提供更直接益处的功能。

与第三方 C 扩展的二进制兼容性问题无关,分离版本控制(如上所述)还有其他好处。

为什么标准库发布中没有二进制兼容的 C ABI 扩展?

可以认为,对 CPython C ABI 的添加在标准库发布中是合理的。这将使 C 扩展作者像其他任何包或模块作者一样自由地依赖特定的语言版本或标准库版本。

本 PEP 目前将解释器版本与语言版本相关联,因此将主要的解释器更改(包括 C ABI 添加)限制在语言发布中。

一个替代的、内部一致的方案是将解释器版本与标准库版本相关联,只有可能影响向后兼容性的更改才限制在语言发布中。

在该方案下,以下更改在标准库发布中是可接受的:

  • 标准库更新
    • 纯 Python 模块中的新功能
    • C 扩展模块中的新功能(受 PEP 399 兼容性要求约束)
    • 语言内置函数中的新功能
  • 解释器实现更新
    • C ABI 的二进制兼容添加
    • 对不影响 AST 或更改字节码魔术号的编译工具链的更改
    • 核心解释器 eval 循环的更改
  • 相应维护版本的错误修复

以下更改在语言发布中是可接受的:

  • 新的语言语法
  • 标准库发布中可接受的任何更新
  • 新的弃用警告
  • 移除先前已弃用的功能
  • AST 的更改
  • 需要更改魔术号的字节码更改
  • C ABI 的二进制不兼容更改(尽管 PEP 384 稳定 ABI 仍须保留)

虽然这种方法可能奏效,但似乎没有令人信服的理由支持它,而 PEP 中当前描述的方法更简单易懂。

为什么不将标准库完全分离出去?

一个偶尔被讨论的概念是使标准库真正独立于 CPython 参考实现。

我个人认为,实际进行这样的更改将花费大量精力却几乎没有回报。没有标准库的 CPython 是无用的(构建链甚至无法运行,测试套件更不用说)。你也无法创建独立的纯 Python 标准库,因为太多“标准库模块”实际上与各自解释器的内部细节紧密相连(例如,内置函数、weakrefgcsysinspectast)。

创建一个与先前语言版本兼容的独立 CPython 开发分支,并从此分支发布标识为单独标准库版本号的版本,应该能提供独立标准库存储库的大部分好处,而痛苦却小得多。

致谢

感谢 PEP 407 的作者开启了这次讨论,也感谢那些作者和 Larry Hastings 对本 PEP 所提议的初步讨论。

参考资料


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

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