PEP 421 – 添加 sys.implementation
- 作者:
- Eric Snow <ericsnowcurrently at gmail.com>
- BDFL 委托:
- Barry Warsaw
- 状态:
- 最终版
- 类型:
- 标准跟踪
- 创建日期:
- 2012年4月26日
- Python 版本:
- 3.3
- 发布历史:
- 2012年4月26日
- 决议:
- Python-Dev 消息
摘要
本 PEP 为 sys
模块引入了一个新属性:sys.implementation
。该属性包含有关正在运行的解释器实现的综合信息。因此,sys.implementation
是标准库可以查找实现特定信息的来源。
本 PEP 中的提议与更广泛地强调使 Python 对替代实现更友好的方向一致。它描述了新变量以及该变量所包含内容的约束。PEP 还解释了 sys.implementation
的一些即时用例。
动机
多年来,Python 语言与 CPython(参考实现)之间的区别越来越大。这一变化主要归因于 Jython、IronPython 和 PyPy 作为可行的 Python 替代实现的出现。
然而,请考虑 CPython 占据主导地位的近二十年 Python(即其大部分存在时间)。这种关注可以理解地导致了标准库和解释器中暴露的许多 CPython 特有的产物。尽管核心开发人员近年来一直在努力解决这个问题,但仍有相当多的产物存在。
本 PEP 提出了解决方案的一部分:一个用于整合实现细节的单一命名空间。这将有助于集中精力区分实现细节和语言。此外,它将促进多实现思维。
提案
我们将在 sys
模块中添加一个新属性,名为 sys.implementation
,它是一个具有属性访问(而非映射)的对象。它将包含实现特定信息。
此对象的属性在解释器执行期间以及在实现版本的整个过程中保持固定。这确保了依赖于 sys.implementation
属性的行为在版本之间不会改变。
该对象具有以下 必需属性 部分中描述的每个属性。这些属性名称永远不会以下划线开头。标准库和语言定义将仅依赖于这些必需属性。
本提案采取保守的方法,只要求少量属性。随着更多属性变得合适,它们可以酌情添加,如 添加新的必需属性 中所述。
虽然本 PEP 没有对 sys.implementation
施加其他限制,但它也建议不要依赖此处描述之外的功能。此建议的唯一例外是以下划线开头的属性。实现者可以酌情使用它们来存储每个实现的数据。
必需属性
这些是 sys.implementation
中的属性,标准库和语言定义将依赖它们,这意味着实现者必须定义它们
- 名称
- 表示实现的全部小写标识符。示例包括 'pypy'、'jython'、'ironpython' 和 'cpython'。
- version
- 实现的版本,而非其实现的语言版本。此值符合 版本格式 中描述的格式。
- hexversion
- 与
sys.hexversion
相同的十六进制格式的实现版本。 - cache_tag
- 用于 PEP 3147 缓存标签的字符串。它通常是名称和版本的组合(例如 CPython 3.3 的 'cpython-33')。但是,实现可以明确使用不同的缓存标签。如果将
cache_tag
设置为 None,则表示应禁用模块缓存。
添加新的必需属性
最终,将向 sys.implementation
添加更多必需属性。但是,每个属性都必须在所有 Python 实现中具有有意义的用例才能被考虑。标准库或语言规范中的用例最能说明这一点。
所有关于新必需属性的提案都将通过正常的 PEP 流程。这样的 PEP 不必很长,只需足够长即可。它需要充分阐述新属性的基本原理、其用例以及它将对各种 Python 实现产生的影响。
版本格式
sys.implementation
的一个主要目的是包含将在标准库内部使用的信息。为了促进版本属性的实用性,其值应在不同实现中保持一致的格式。
因此,sys.implementation.version
的格式将遵循 sys.version_info
的格式,后者实际上是一个命名元组。这是一种熟悉的格式,并且通常与正常的版本格式约定一致。
基本原理
现状中,特定于实现的信息以一种更脆弱、更难维护的方式提供。它分散在不同的模块中,或者从其他信息中推断出来,正如我们在 platform.python_implementation() 中看到的那样。
本 PEP 是这种方法的主要替代方案。它将特定于实现的信息整合到一个命名空间中,并使隐式的信息变得显式。
类型考虑
很容易陷入关于 sys.implementation
类型的讨论。然而,它的目的是支持标准库和语言定义。因此,关于其类型并没有太多真正重要的事情,与更普遍使用的特性相比。因此,像不可变性和序列性这样的特性已被忽略。
唯一的真正选择是在具有属性访问的对象和具有项访问的映射之间。本 PEP 倡导使用点号访问来反映命名空间的相对固定性质。
非必需属性
本 PEP 的早期版本包含一个名为 metadata
的必需属性,它保存了任何非必需的、特定于实现的数据 [12]。然而,考虑到 sys.implementation
的目的,这被证明是一个不必要的添加。
最终,本 PEP 中几乎忽略了非必需属性。除了粗心使用可能与未来必需属性冲突之外,它们没有其他影响。然而,对于 sys.implementation
来说,这只是一个微不足道的担忧。
为什么是 sys
的一部分?
sys
模块持有新的命名空间,因为 sys
是以解释器为中心的变量和函数的存储库。许多特定于实现的属性已在 sys
中找到。
为什么对任何值都有严格的限制?
如 版本格式 中所述,sys.implementation
中的值旨在供标准库使用。限制这些值,本质上是为它们指定 API,允许它们被一致地使用,而不管它们如何以其他方式实现。但是,应注意不要过度指定约束。
讨论
sys.implementation
的话题在 2009 年的 python-ideas 列表中提出,当时受到了普遍的积极反响 [1]。我最近在研究纯 Python imp.get_tag()
时重新引发了讨论 [2]。讨论一直在进行 [3]。issue #14673 中的消息也与此相关。
最近讨论的一个重要部分集中在用于 sys.implementation
的类型。
用例
platform.python_implementation()
“显式优于隐式”
platform
模块通过在几个不同的 sys
变量中寻找线索来确定 python 实现 [9]。然而,这种方法很脆弱,每次实现更改时都需要更改标准库。除此之外,platform
中的支持仅限于核心开发人员通过在 platform
模块中进行特殊处理而批准的那些实现。
有了 sys.implementation
,各种实现将明确地在它们自己的 sys
模块版本中设置这些值。
另一个问题是 platform
模块是 stdlib 的一部分,理想情况下它应该尽量减少实现细节,例如那些将移至 sys.implementation
的细节。
sys.implementation
和 platform
模块之间的任何重叠都将简单地遵循 sys.implementation
(platform
中具有相同接口的包装器)。
冻结的 Importlib 中的缓存标签生成
PEP 3147 定义了模块缓存和文件名的缓存标签的使用。在 3.3 中作为 Python 二进制文件冻结的 importlib 引导代码在导入过程中使用缓存标签。引导 importlib 项目的一部分是清理 Python/import.c 中不再需要的代码。
Python/import.c
中定义的缓存标签被硬编码为 "cpython" MAJOR MINOR
。对于 importlib,选项要么是以同样的方式硬编码,要么以 platform.python_implementation()
的方式猜测实现。
只要硬编码标签仅限于 CPython 特定的代码,它就是可行的。然而,鉴于其他 Python 实现使用 importlib 代码来处理模块缓存,硬编码标签将成为一个问题。
在这种情况下,直接使用 platform
模块是不可行的。importlib 引导中使用的任何模块都必须是内置的或冻结的,这两者都不适用于 platform
模块。这就是导致最近对 sys.implementation
产生兴趣的原因。
无论用于实现的名称结果如何,另一个问题与缓存标签中使用的版本有关。该版本可能是实现版本而不是语言版本。然而,实现版本在标准库中并未明确标识。
特定于实现的测试
目前,Lib/test
下的测试套件中有许多实现特定的测试。测试支持模块 (Lib/test/support.py) 提供了一些处理这些测试的功能。然而,像 platform
模块一样,test.support
必须进行一些猜测,而 sys.implementation
将使其变得不必要。
Jython 的 os.name
hack
在 Jython 中,os.name
被设置为“java”,以适应标准库中对 Java 环境的特殊处理 [10] [11]。不幸的是,它掩盖了本应在此处的操作系统名称。sys.implementation
将有助于消除对这种特殊情况的需求。目前 Jython 为正常的 os.name
值设置了 os._name
。
与 sys.(version|version_info|hexversion)
的问题
本 PEP 的早期版本错误地将 sys.version_info
(及相关内容)称为 Python 语言的版本,而不是实现的版本。然而,情况并非如此。相反,它是 CPython 实现的版本。顺便说一句,sys.version_info
的前两个组件(主要和次要)也反映了语言定义的版本。
正如 Barry Warsaw 指出的那样,“sys.version_info 的语义过去一直相当模糊” [13]。有了 sys.implementation
,我们有机会通过首先建立一个明确的实现版本位置来改善这种情况。
本 PEP 没有做出其他努力来直接澄清 sys.version_info
的语义。无论如何,拥有一个明确的实现版本肯定有助于澄清与语言版本之间的区别。
来自其他 Python 实现者的反馈
IronPython
Jeff Hardy 回复了反馈请求 [4]。他说:“它一获批,我可能第二天就会添加它” [5]。他还就 sys.implementation
的类型和 metadata
属性(此后已从 PEP 中删除)提供了有用的反馈。
Jython
2009 年,Frank Wierzbicki 曾这样说(关于 Jython 实现必需属性) [6]
Speaking for Jython, so far it looks like something we would adopt
soonish after it was accepted (it looks pretty useful to me).
PyPy
一些 PyPy 开发者回应了反馈请求 [7]。Armin Rigo 说了以下内容 [8]
For myself, I can only say that it looks like a good idea, which we
will happily adhere to when we migrate to Python 3.3.
他还表示支持将所需列表保持小范围。Armin 和 Laura Creighton 都表示,更好地编目 Python 实现的努力将受到欢迎。这种努力,本 PEP 是一个小小的开始,将单独考虑。
过往努力
PEP 3139
2008 年的 PEP 3139 建议清理 sys
模块,部分方法是将特定于实现的变量和函数提取到一个单独的模块中。PEP 421 是该想法的一个不那么雄心勃勃的版本。虽然 PEP 3139 被拒绝,但其目标在很大程度上反映在 PEP 421 中,尽管方法要轻得多。
PEP 399
更广阔的视角
值得再次指出,本 PEP 是正在进行的一项更大努力的一小部分,该努力旨在识别 Python 中特定于实现的部分并减轻其对替代实现的影响。
sys.implementation
是特定于实现的数据的焦点,充当语言、标准库和不同实现之间合作的纽带。随着时间的推移,sys.implementation
有可能在适当的情况下承担 sys
和其他内置/标准库模块的当前属性。通过这种方式,它是一个精简版 PEP 3137,但尽可能小。
然而,正如已经指出的,许多其他努力早于 sys.implementation
。它也并非一定是这项努力的主要部分。相反,将其视为使 Python 对替代实现更友好这项努力的基础设施的一部分。
备选方案
由于 sys 下的单一命名空间方法相对简单,因此本 PEP 没有考虑其他替代方案。
其他属性的示例
这些仅是示例,不属于提案的一部分。其中大部分是在之前的讨论中提出的,但与本 PEP 的目标不符。(如果它们让您兴奋,请参阅 添加新的必需属性。)
- common_name
- 实现的已知大小写敏感名称。
- vcs_url
- 实现项目主要 VCS 存储库的 URL。
- vcs_revision_id
- 标识实现 VCS 修订的值。
- build_toolchain
- 用于构建解释器的工具。
- build_date
- 解释器构建的时间戳。
- 主页
- 实现网站的 URL。
- site_prefix
- 实现的首选站点前缀。
- 运行时
- 解释器正在运行的运行时环境,例如 “.NET CLR” 或 “Java 运行时可执行文件”。
- gc_type
- 使用的垃圾收集类型,例如“引用计数”或“标记清除”。
未解决的问题
目前没有。
实施
本 PEP 的实现涵盖在 issue #14673 中。
参考资料
- (2009) Dino Viehland 发表他的观点:https://mail.python.org/pipermail/python-dev/2009-October/092894.html
platform
代码:https://hg.python.org/cpython/file/2f563908ebc5/Lib/platform.py#l1247- CPython 中缓存标签的原始实现:https://hg.python.org/cpython/file/2f563908ebc5/Python/import.c#l121
- test.support 中实现特定处理的示例
os.name
用作“java”。https://hg.python.org/cpython/file/2f563908ebc5/Lib/test/support.py#l512sys.implementation.metadata
的提案:https://mail.python.org/pipermail/python-ideas/2012-May/014984.html版权
本文档已置于公共领域。
来源:https://github.com/python/peps/blob/main/peps/pep-0421.rst
最后修改时间:2024-12-06 18:17:22 GMT