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

Python 增强提案

PEP 364 – 过渡到 Py3K 标准库

作者:
Barry Warsaw <barry at python.org>
状态:
已撤回
类型:
标准跟踪
创建:
2007年3月1日
Python 版本:
2.6
历史记录:


目录

摘要

PEP 3108 描述了 Python 3.0 版本中 Python 标准库的重组。本 PEP 描述了一种从 Python 2.x 标准库过渡到 Python 3.0 标准库的机制。此过渡将允许和鼓励 Python 程序员从 Python 2.6 开始使用新的 Python 3.0 库名称,同时为了向后兼容性保留旧名称。通过这种方式,Python 程序员可以编写向前兼容的代码,而不会牺牲与现有 Python 程序的互操作性。

基本原理

PEP 3108 提供了 Python 标准库 (stdlib) 重组的基本原理。鼓励读者查阅该 PEP 以了解库将如何重组以及重组的原因。如果 PEP 3108 被部分或全部接受,那么允许 Python 程序员在 Python 2.x 中开始过渡到新的 stdlib 模块名称将是有利的,以便他们可以从 Python 2.6 开始编写向前兼容的代码。

请注意,PEP 3108 提议删除一些“愚蠢的旧东西”,即不再有用或必要的模块。您正在阅读的 PEP 没有解决这个问题,因为对于要删除的模块没有向前兼容性问题,除了停止使用此类模块之外。

本 PEP 仅涉及维护从旧 stdlib 名称到新 stdlib 名称映射的机制。请查阅 PEP 3108 以了解所有具体的模块重命名提案。具体来说,请参阅标题为 Modules to Rename 的部分,了解旧名称到新名称映射的指南。本 PEP 中的几个示例仅用于说明目的,不应用于具体的重命名建议。

支持的重命名

本 PEP 明确支持至少 4 种用例

  • 简单的顶级包名称重命名,例如 StringIO 重命名为 stringio;
  • 子包重命名,其中包名称可能被重命名也可能不被重命名,例如 email.MIMEText 重命名为 email.mime.text;
  • 扩展模块重命名,例如 cStringIO 重命名为 cstringio;
  • 第三方重命名上述任何一项。

本 PEP 支持的两种用例包括重命名简单的顶级模块,例如 StringIO,以及包中的模块,例如 email.MIMEText

在前面一种情况下,PEP 3108 目前建议将 StringIO 重命名为 stringio,遵循 PEP 8 的建议。

在后一种情况下,与 Python 2.5 一起分发的 email 4.0 包已将 email.MIMEText 重命名为 email.mime.text,尽管它是在 email 包内部以一种一次性、独特的、非正统的方式完成的。本 PEP 中描述的机制足够通用,可以处理所有模块重命名,从而无需 Python 2.5 的 hack(除了与早期 Python 版本的向后兼容性)。

另一个用例是支持 C 扩展模块的重命名。只要 C 模块的新名称可导入,就可以将其重新映射到新名称。例如,cStringIO 重命名为 cstringio

第三方包重命名也受支持,通过任何 Python 模块都可以访问的几个公共接口。

重映射不会递归执行。

.mv 文件

重映射文件称为 .mv 文件;选择此后缀是为了让人联想到 Unix mv(1) 命令。 .mv 文件是一个简单的面向行的文本文件。所有空行和以 # 开头的行都被忽略。所有其他行都必须包含两个空格分隔的字段。第一个字段是旧模块名称,第二个字段是新模块名称。两个模块名称都必须使用其完整的点分路径名称指定。以下是从 Python 2.6 中提取的 .mv 文件示例

# Map the various string i/o libraries to their new names
StringIO    stringio
cStringIO   cstringio

.mv 文件可以出现在文件系统的任何位置,并且提供了一个程序接口来解析它们并在其中注册重映射。默认情况下,当 Python 启动时,会读取 oldlib 包中的所有 .mv 文件,并自动注册其中找到的所有重映射。这就是应该为顶级 Python 2.x 标准库模块指定所有模块重映射的位置。

实现规范

本节提供了 Python 2.x 中模块重命名实现方式的完整规范。核心机制依赖于 PEP 302 中描述的各种导入钩子。具体来说,sys.path_importer_cachesys.pathsys.meta_path 都被用来提供必要的功能。

当 Python 的导入机制初始化时,会导入 oldlib 包。在 oldlib 内部,有一个名为 OldStdlibLoader 的类。此类实现了 PEP 302 接口,并且会自动实例化,且无需参数。构造函数读取 oldlib 包目录中的所有 .mv 文件,自动注册在这些 .mv 文件中找到的所有重映射。这就是 Python 2.x 标准库如何重新映射的方式。

其他 Python 模块不应实例化 OldStdlibLoader 类。相反,您可以通过 sys.stdlib_remapper 实例访问全局 OldStdlibLoader 实例。如果您希望以编程方式访问重映射机制,请使用此实例。

一个重要的实现细节:根据 PEP 302 API 的需要,一个魔术字符串被添加到 sys.path 和模块的 __path__ 属性中,以便挂接我们的重映射加载器。此魔术字符串当前为 <oldlib>,并且为了将所有以 < 开头的 sys.path 条目视为特殊条目,Python 的 site.py 文件需要进行一些更改。具体来说,不会尝试将它们设为绝对文件名(因为它们根本不是文件名)。

为了使重映射导入钩子起作用,模块或包必须物理地位于其新名称下。这是因为导入钩子仅捕获尚未导入的模块,并且无法通过 Python 的内置导入规则导入。因此,如果某个模块已被移动,例如从 Lib/StringIO.py 移动到 Lib/stringio.py,并且前者的 .pyc 文件已被删除,那么如果没有重映射器,这将失败

import StringIO

相反,使用重映射器,此失败的导入将被捕获,旧名称将在注册的重映射中查找,在这种情况下,将找到新名称 stringio。然后,重映射器尝试导入新名称,如果成功,它会将生成的模块绑定到 sys.modules 中,并在旧名称和新名称下都使用。因此,上述导入将导致 sys.modules 中出现 ‘StringIO’ 和 ‘stringio’ 的条目,并且两者都将指向完全相同的模块对象。

请注意,没有建议禁用重映射机制的方法,除非将所有 .mv 文件移开或在某些自定义启动代码中以编程方式删除它们。在 Python 3.0 中,重映射将被消除,只保留“新”名称。

程序接口

一些方法被添加到 sys.stdlib_remapper 对象中,第三方包可以使用这些方法来注册他们自己的重映射。但是请注意,在所有情况下,从旧名称到新名称都只有一个映射。如果两个 .mv 文件包含旧名称的不同映射,或者如果使用已重新映射的旧名称进行编程调用,则先前的映射将丢失。这不会影响任何已导入的模块。

以下方法可用于 sys.stdlib_remapper 对象

  • read_mv_file(filename) – 读取给定文件并注册在文件中找到的所有重映射。
  • read_directory_mv_files(dirname, suffix='.mv') – 列出给定目录,读取该目录中所有具有匹配后缀(默认为 .mv)的文件。对于每个解析的文件,注册在该文件中找到的所有重映射。
  • set_mapping(oldname, newname) – 注册从旧模块名称到新模块名称的新映射。两者都必须是模块的完整点分路径名称。newname 可以为 None,在这种情况下,将删除 oldname 的任何现有映射(如果不存在现有映射,则不会出错)。
  • get_mapping(oldname, default=None) – 返回给定 oldname 的任何已注册的 newname。如果未注册重映射,则返回 default。

未解决的问题

  • 是否应该有一个命令行开关和/或环境变量来禁用所有重映射?
  • 重映射是否应该递归发生?
  • 当加载包的 __init__.py 时,我们是否应该自动解析包目录中的 .mv 文件?这将允许包轻松地为自己的重映射包含 .mv 文件。比较一下,如果我们将 email 包的 .mv 文件放在 email 包中而不是 oldlib 包中,email 包当前需要做什么
    # Expose old names
    import os, sys
    sys.stdlib_remapper.read_directory_mv_files(os.path.dirname(__file__))
    

    我认为我们应该自动读取包目录中可能包含的任何 .mv 文件。

参考实现

参考实现,以针对 Python 2.6 svn 主干当前(截至本文撰写时)状态的补丁的形式提供,可在 SourceForge 补丁 #1675334 [1] 中找到。请注意,此补丁包括将 cStringIO 重命名为 cstringio,但这主要是为了说明和单元测试的目的。如果接受此补丁,我们可能希望将此更改拆分到其他 PEP 3108 更改中。

参考文献


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

最后修改时间:2023-09-09 17:39:29 GMT