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-02-24
更新历史:
2012-02-24, 2012-02-25

目录

PEP 撤回

随着 PEP 453 的通过,意味着 pip 将默认情况下可用于大多数新的 Python 用户,这将有望减轻在模块足够成熟之前将其添加到标准库的压力。

过去几年也见证了这种模式的增加使用,其中标准库包在 Python 包索引中也提供了一个等效的版本,该版本也支持旧版本的 Python。

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

摘要

本 PEP 提出采用与现有语言版本方案不同但与之相关的独立版本方案,该方案允许加速发布 Python 标准库,同时保持(甚至减慢)核心语言定义的当前变化速度。

PEP 407 一样,它旨在调整当前衡量变化之间的平衡,这种变化使更广泛的社区有时间适应,并能够跟上比当前发布周期所能处理的更快变化的外部影响(这个问题对于与 Web 技术相关的标准库元素尤其明显)。

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

理由

引用 PEP 407 摘要

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

当前的发布周期过于保守。它适合重视稳定性而不是反应性的人。本 PEP 试图保持 Python 商标的稳定性,同时通过引入长期支持版本的概念,提供更灵活的功能发布。

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

但是,我写了这个竞争的 PEP,因为我认为 PEP 407 中提出的每 6 个月提供完整的、可能不兼容二进制版本的 CPython 的方法给更广泛的 Python 生态系统带来了过大的负担。

在当前的 CPython 发布周期下,关键二进制扩展的发布者通常会在 CPython 分支进入“仅安全修复”模式后继续支持 Python 版本(例如,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 更匮乏)将面临一个不可接受的选择:要么自己采用更快的发布周期(最多 18 个 PyGame 的同时二进制发布版本!),要么更快地放弃旧的 Python 版本,要么告诉他们的用户坚持使用 CPython LTS 版本(从而完全违背了加快 CPython 发布周期的初衷)。

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

在文化层面上,Python 社区也习惯了 Python 版本号的特定含义——它们与弃用期、支持期以及其他各种事物相关联。 PEP 407 提出将所有集体知识抛诸脑后,却没有提供令人信服的理由说明为什么这种行动方案实际上是必要的(除了也许让 CPython 核心开发者更容易,但以牺牲其他所有人为代价)。

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

提案

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

  • 语言发布:“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 语言发布版本的主版本号和次版本号组合成一个两位数,然后追加一个连续的标准库版本标识符来构造。

发布周期

创建维护发布版本时,实际上会在 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]

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

对于维护发布版本,处理非周期性发布版本(例如,为了修复安全问题或解决新发布版本中的严重错误)的过程与现在相同:次版本号加 1,并发布一个新的版本,其中包含所需的错误修复以及自上次发布版本以来提交的所有其他错误修复。

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

用户场景

上面提出的版本控制方案基于一些用户场景,这些场景很可能会在方案被采纳后遇到。在每种情况下,都将描述现状(即缓慢的发布周期)、本文中的版本控制方案以及在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 版本很少发布,但包含标准库更新、核心语言定义和解释器更改的混合体。

本文中的 PEP:标准库更新(更容易集成)以更清晰明确地与先前版本语言定义兼容的方式更频繁地提供。这意味着一旦备用实现赶上 Python 3.3,它们应该更容易地随着时间的推移合并标准库功能(尤其是纯 Python 更改),将小版本号更新作为唯一需要更新其核心编译和执行组件的任务。

PEP 407(完整版本):与现状相同,但这种情况发生的频率会更高。

PEP 407(语言更新仅限于 LTS 版本):尚不清楚,因为 PEP 目前没有明确说明具体的开发策略。假设采用 3.3 兼容性分支(如本文中的 PEP 中所建议的那样),那么结果将基本相同,但版本号信号会略微不那么清晰(因为您需要检查特定版本是 LTS 版本还是非 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维护分支关闭的同时,3.3-compat分支也将关闭正常开发。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 文件的合并冲突已经很麻烦了。由于本 PEP 提议在正常工作流程中引入额外的分支,因此解决这个问题变得更加关键。虽然 Mercurial 阶段可以在一定程度上有所帮助,但最好完全消除这个问题。

Barry Warsaw 的一个建议是采用与 Twisted [2] 相似的每个更改使用单独文件的无冲突方法。

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

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 年*(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 的二进制安装程序创建涉及几个手动步骤(包括手动测试)以及在我们没有单独的“-release”树仅接收被稳定构建机器人标记为良好的版本的情况下是不切实际的,但它仍然是一个有用的标准,在考虑提议的新版本方案时需要牢记在心:如果我们最终想让标准库版本比每 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 符号链接,以直接引用所需的发布系列)意味着这种简单的选择出于历史原因不可行。

这种简单方法的一种可行方式是将当前的主版本号和次版本号直接合并到一个两位数的主版本号中

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

最后修改:2023-10-11 12:05:51 GMT