Python 3.3 中的新增功能

本文档解释了 Python 3.3 相对于 3.2 的新功能。Python 3.3 于 2012 年 9 月 29 日发布。有关完整详细信息,请参阅更新日志

参见

PEP 398 - Python 3.3 发布计划

摘要 – 发布亮点

新语法功能

  • 新的 yield from 表达式,用于生成器委托

  • 对于 str 对象,再次接受 u'unicode' 语法。

新库模块

  • faulthandler (有助于调试低级崩溃)

  • ipaddress (表示 IP 地址和掩码的高级对象)

  • lzma (使用 XZ / LZMA 算法压缩数据)

  • unittest.mock (用 mock 对象替换测试系统的一部分)

  • venv (Python 虚拟环境,如流行的 virtualenv 包)

新的内置功能

实现改进

显著改进的库模块

安全改进

  • 哈希随机化默认启用。

请继续阅读以获取用户可见更改的完整列表。

PEP 405:虚拟环境

虚拟环境有助于在共享系统范围的基础安装的同时创建单独的 Python 设置,以便于维护。虚拟环境拥有自己的私有 site-packages(即本地安装的库),并且可以选择与系统范围的 site-packages 分离。它们的理念和实现受到流行的第三方 virtualenv 包的启发,但受益于与解释器核心更紧密的集成。

此 PEP 添加了用于编程访问的 venv 模块,以及用于命令行访问和管理的 pyvenv 脚本。Python 解释器检查 pyvenv.cfg 文件,其存在表示虚拟环境目录树的根目录。

参见

PEP 405 - Python 虚拟环境

PEP 由 Carl Meyer 编写;由 Carl Meyer 和 Vinay Sajip 实现

PEP 420:隐式命名空间包

对不需要 __init__.py 标记文件并可以自动跨多个路径段的包目录的原生支持(受各种第三方命名空间包方法的启发,如 PEP 420 中所述)

参见

PEP 420 - 隐式命名空间包

PEP 由 Eric V. Smith 编写;由 Eric V. Smith 和 Barry Warsaw 实现

PEP 3118:新的 memoryview 实现和缓冲区协议文档

PEP 3118 的实现已显著改进。

新的 memoryview 实现全面修复了 Py_buffer 结构中动态分配字段的所有所有权和生命周期问题,这些问题曾导致多个崩溃报告。此外,修复了对非连续或多维输入崩溃或返回不正确结果的几个函数。

memoryview 对象现在有一个符合 PEP-3118 的 getbufferproc(),它会检查消费者的请求类型。增加了许多新功能,其中大部分对非连续数组和带子偏移量的数组都通用。

文档已更新,明确阐明了导出者和消费者的职责。缓冲区请求标志分为基本标志和复合标志。解释了非连续和多维 NumPy 风格数组的内存布局。

功能

  • 现在支持结构模块语法中所有原生单字符格式说明符(可选前缀为“@”)。

  • 在某些限制下,cast() 方法允许更改 C 连续数组的格式和形状。

  • 支持任何数组类型的多维列表表示。

  • 支持任何数组类型的多维比较。

  • 格式为 B、b 或 c 的可哈希(只读)类型的一维内存视图现在可哈希。(由 Antoine Pitrou 在bpo-13411 中贡献。)

  • 支持任意一维数组类型的切片。例如,现在可以通过使用负步长在 O(1) 时间内反转内存视图。

API 变更

  • 最大维数官方限制为 64。

  • 空形状、步幅和子偏移量的表示现在是空元组,而不是 None

  • 使用格式 'B'(无符号字节)访问 memoryview 元素现在返回一个整数(根据结构模块语法)。要返回字节对象,必须首先将视图转换为 'c'。

  • memoryview 比较现在使用操作数的逻辑结构并按值比较所有数组元素。支持结构模块语法中的所有格式字符串。仍允许使用无法识别的格式字符串的视图,但无论视图内容如何,它们将始终比较为不相等。

  • 有关进一步更改,请参阅构建和 C API 更改移植 C 代码

(由 Stefan Krah 在bpo-10181 中贡献。)

参见

PEP 3118 - 修订缓冲区协议

PEP 393:灵活的字符串表示

Unicode 字符串类型已更改为支持多种内部表示,具体取决于所表示字符串中具有最大 Unicode 序数(1、2 或 4 字节)的字符。这在常见情况下允许空间高效的表示,但在所有系统上都可以访问完整的 UCS-4。为了与现有 API 兼容,可能会并行存在多种表示;随着时间的推移,这种兼容性应该逐步淘汰。

在 Python 方面,此更改应该没有负面影响。

在 C API 方面,PEP 393 完全向后兼容。旧版 API 应该至少保留五年。使用旧版 API 的应用程序将无法完全受益于内存减少,甚至可能使用更多内存,因为 Python 可能必须维护每个字符串的两个版本(旧版格式和新版高效存储)。

功能

PEP 393 引入的更改如下

  • Python 现在始终支持完整的 Unicode 码点范围,包括非 BMP 码点(即从 U+0000U+10FFFF)。窄构建和宽构建之间的区别不再存在,Python 现在表现得像一个宽构建,即使在 Windows 下也是如此。

  • 随着窄构建的消亡,窄构建特有的问题也得到了修复,例如

    • len() 现在始终对非 BMP 字符返回 1,因此 len('\U0010FFFF') == 1

    • 代理对在字符串文字中不再重新组合,因此 '\uDBFF\uDFFF' != '\U0010FFFF'

    • 索引或切片非 BMP 字符返回预期值,因此 '\U0010FFFF'[0] 现在返回 '\U0010FFFF' 而不是 '\uDBFF'

    • 标准库中的所有其他函数现在都能正确处理非 BMP 码点。

  • sys.maxunicode 的值现在始终为 1114111(十六进制为 0x10FFFF)。PyUnicode_GetMax() 函数为了向后兼容性仍然返回 0xFFFF0x10FFFF,并且不应与新的 Unicode API 一起使用(参见bpo-13054)。

  • ./configure 标志 --with-wide-unicode 已移除。

性能和资源使用

Unicode 字符串的存储现在取决于字符串中最高的码点

  • 纯 ASCII 和 Latin1 字符串(U+0000-U+00FF)每个码点使用 1 字节;

  • BMP 字符串(U+0000-U+FFFF)每个码点使用 2 字节;

  • 非 BMP 字符串(U+10000-U+10FFFF)每个码点使用 4 字节。

最终结果是,对于大多数应用程序而言,字符串存储的内存使用量应显著减少——特别是与以前的宽 Unicode 构建相比——因为在许多情况下,即使在国际环境中,字符串也将是纯 ASCII(因为许多字符串存储非人类语言数据,例如 XML 片段、HTTP 头、JSON 编码数据等)。我们还希望,出于相同的原因,它将提高非平凡应用程序的 CPU 缓存效率。在 Django 基准测试中(详见 PEP),Python 3.3 的内存使用量是 Python 3.2 的两到三倍小,并且比 Python 2.7 稍好。

参见

PEP 393 - 灵活的字符串表示

PEP 由 Martin von Löwis 撰写;由 Torsten Becker 和 Martin von Löwis 实现。

PEP 397:Windows Python 启动器

Python 3.3 Windows 安装程序现在包含一个 py 启动器应用程序,可用于以与版本无关的方式启动 Python 应用程序。

双击 *.py 文件时,此启动器会隐式调用。如果系统上只安装了一个 Python 版本,则该版本将用于运行该文件。如果安装了多个版本,则默认使用最新版本,但可以通过在 Python 脚本中包含 Unix 风格的“shebang 行”来覆盖此设置。

启动器也可以作为 py 应用程序从命令行显式使用。运行 py 遵循与隐式启动脚本相同的版本选择规则,但可以通过传递适当的参数来选择更具体的版本(例如,当还安装了 Python 2 时请求 Python 3 的 -3,或者当安装了更新版本时专门请求早期 Python 版本的 -2.6)。

除了启动器,Windows 安装程序现在还包含一个选项,可以将新安装的 Python 添加到系统 PATH。(由 Brian Curtin 在bpo-3561 中贡献。)

参见

PEP 397 - Windows Python 启动器

PEP 由 Mark Hammond 和 Martin v. Löwis 撰写;由 Vinay Sajip 实现。

启动器文档:Python 安装管理器

安装程序 PATH 修改:Python 安装管理器

PEP 3151:重构操作系统和 IO 异常层次结构

由操作系统错误引发的异常层次结构现在既简化又更细粒度。

您不再需要担心在 OSErrorIOErrorEnvironmentErrorWindowsErrormmap.errorsocket.errorselect.error 之间选择适当的异常类型。所有这些异常类型现在都只是一种:OSError。其他名称仍作为别名保留,以实现兼容性。

此外,现在更容易捕获特定的错误情况。您无需检查 errno 属性(或 args[0])以获取 errno 模块中的特定常量,而是可以捕获适当的 OSError 子类。可用的子类如下

ConnectionError 本身具有更细粒度的子类

得益于新的异常,现在可以避免 errno 的常见用法。例如,以下为 Python 3.2 编写的代码

from errno import ENOENT, EACCES, EPERM

try:
    with open("document.txt") as f:
        content = f.read()
except IOError as err:
    if err.errno == ENOENT:
        print("document.txt file is missing")
    elif err.errno in (EACCES, EPERM):
        print("You are not allowed to read document.txt")
    else:
        raise

现在可以不导入 errno 并且无需手动检查异常属性即可编写

try:
    with open("document.txt") as f:
        content = f.read()
except FileNotFoundError:
    print("document.txt file is missing")
except PermissionError:
    print("You are not allowed to read document.txt")

参见

PEP 3151 - 重构操作系统和 IO 异常层次结构

PEP 由 Antoine Pitrou 撰写并实现

PEP 380:委托给子生成器的语法

PEP 380 添加了 yield from 表达式,允许 生成器 将其部分操作委托给另一个生成器。这允许将包含 yield 的代码段提取出来并放置在另一个生成器中。此外,子生成器被允许带返回值返回,并且该值可供委托生成器使用。

虽然 yield from 表达式主要用于委托给子生成器,但它实际上允许委托给任意子迭代器。

对于简单的迭代器,yield from iterable 本质上只是 for item in iterable: yield item 的缩写形式

>>> def g(x):
...     yield from range(x, 0, -1)
...     yield from range(x)
...
>>> list(g(5))
[5, 4, 3, 2, 1, 0, 1, 2, 3, 4]

然而,与普通循环不同,yield from 允许子生成器直接从调用范围接收发送和抛出的值,并向外部生成器返回最终值

>>> def accumulate():
...     tally = 0
...     while 1:
...         next = yield
...         if next is None:
...             return tally
...         tally += next
...
>>> def gather_tallies(tallies):
...     while 1:
...         tally = yield from accumulate()
...         tallies.append(tally)
...
>>> tallies = []
>>> acc = gather_tallies(tallies)
>>> next(acc)  # Ensure the accumulator is ready to accept values
>>> for i in range(4):
...     acc.send(i)
...
>>> acc.send(None)  # Finish the first tally
>>> for i in range(5):
...     acc.send(i)
...
>>> acc.send(None)  # Finish the second tally
>>> tallies
[6, 10]

推动这一变化的主要原则是,即使是设计用于 sendthrow 方法的生成器,也可以像将单个大型函数拆分为多个子函数一样容易地拆分为多个子生成器。

参见

PEP 380 - 委托给子生成器的语法

PEP 由 Greg Ewing 撰写;由 Greg Ewing 实现,Renaud Blanch、Ryan Kelly 和 Nick Coghlan 集成到 3.3 中;文档由 Zbigniew Jędrzejewski-Szmek 和 Nick Coghlan 撰写

PEP 409:抑制异常上下文

PEP 409 引入了新语法,允许禁用链式异常上下文的显示。这允许在应用程序在异常类型之间进行转换时提供更清晰的错误消息

>>> class D:
...     def __init__(self, extra):
...         self._extra_attributes = extra
...     def __getattr__(self, attr):
...         try:
...             return self._extra_attributes[attr]
...         except KeyError:
...             raise AttributeError(attr) from None
...
>>> D({}).x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in __getattr__
AttributeError: x

如果没有 from None 后缀来抑制原因,则默认会显示原始异常

>>> class C:
...     def __init__(self, extra):
...         self._extra_attributes = extra
...     def __getattr__(self, attr):
...         try:
...             return self._extra_attributes[attr]
...         except KeyError:
...             raise AttributeError(attr)
...
>>> C({}).x
Traceback (most recent call last):
  File "<stdin>", line 6, in __getattr__
KeyError: 'x'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in __getattr__
AttributeError: x

没有丢失调试能力,因为如果需要(例如,如果中间库错误地抑制了有价值的底层细节),原始异常上下文仍然可用

>>> try:
...     D({}).x
... except AttributeError as exc:
...     print(repr(exc.__context__))
...
KeyError('x',)

参见

PEP 409 - 抑制异常上下文

PEP 由 Ethan Furman 撰写;由 Ethan Furman 和 Nick Coghlan 实现。

PEP 414:显式 Unicode 字面量

为了方便 Unicode 敏感的 Python 应用程序从 Python 2 迁移,这些应用程序大量使用 Unicode 字面量,Python 3.3 再次支持字符串字面量的“u”前缀。此前缀在 Python 3 中没有语义意义,它仅用于减少迁移到 Python 3 时纯机械更改的数量,使开发人员更容易专注于更重要的语义更改(例如,二进制数据和文本数据之间更严格的默认分离)。

参见

PEP 414 - 显式 Unicode 字面量

PEP 由 Armin Ronacher 撰写。

PEP 3155:类和函数的限定名

函数和类对象有一个新的 __qualname__ 属性,表示从模块顶层到其定义的“路径”。对于全局函数和类,这与 __name__ 相同。对于其他函数和类,它提供了关于它们实际定义位置以及如何从全局范围访问它们的更好信息。

方法(非绑定)示例

>>> class C:
...     def meth(self):
...         pass
...
>>> C.meth.__name__
'meth'
>>> C.meth.__qualname__
'C.meth'

嵌套类示例

>>> class C:
...     class D:
...         def meth(self):
...             pass
...
>>> C.D.__name__
'D'
>>> C.D.__qualname__
'C.D'
>>> C.D.meth.__name__
'meth'
>>> C.D.meth.__qualname__
'C.D.meth'

嵌套函数示例

>>> def outer():
...     def inner():
...         pass
...     return inner
...
>>> outer().__name__
'inner'
>>> outer().__qualname__
'outer.<locals>.inner'

这些对象的字符串表示也已更改,以包含新的、更精确的信息

>>> str(C.D)
"<class '__main__.C.D'>"
>>> str(C.D.meth)
'<function C.D.meth at 0x7f46b9fe31e0>'

参见

PEP 3155 - 类和函数的限定名

PEP 由 Antoine Pitrou 撰写并实现。

PEP 412:键共享字典

用于存储对象属性的字典现在可以在彼此之间共享其内部存储的一部分(即存储键及其各自哈希值的部分)。这减少了创建许多非内置类型实例的程序的内存消耗。

参见

PEP 412 - 键共享字典

PEP 由 Mark Shannon 撰写并实现。

PEP 362:函数签名对象

新的函数 inspect.signature() 使 Python 可调用对象的内省变得简单直观。支持广泛的可调用对象:Python 函数(无论是否装饰)、类和 functools.partial() 对象。新的类 inspect.Signatureinspect.Parameterinspect.BoundArguments 保存有关调用签名(例如,注释、默认值、参数类型和绑定参数)的信息,这大大简化了编写装饰器和任何验证或修改调用签名或参数的代码。

参见

PEP 362: - 函数签名对象

PEP 由 Brett Cannon、Yury Selivanov、Larry Hastings、Jiwon Seo 撰写;由 Yury Selivanov 实现。

PEP 421:添加 sys.implementation

sys 模块上的新属性公开了当前正在运行的解释器实现的特定详细信息。sys.implementation 的初始属性集是 nameversionhexversioncache_tag

sys.implementation 的目的是将标准库使用的实现特定数据合并到一个命名空间中。这使得不同的 Python 实现更容易共享单个标准库代码库。在初始状态下,sys.implementation 只包含一小部分实现特定数据。随着时间的推移,这个比例会发生变化,以使标准库更具可移植性。

标准库可移植性改进的一个例子是 cache_tag。从 Python 3.3 开始,importlib 使用 sys.implementation.cache_tag 来支持 PEP 3147 兼容性。任何使用 importlib 作为其内置导入系统的 Python 实现都可以使用 cache_tag 来控制模块的缓存行为。

SimpleNamespace

sys.implementation 的实现还引入了 Python 的新类型:types.SimpleNamespace。与基于映射的命名空间(如 dict)不同,SimpleNamespace 是基于属性的,如 object。然而,与 object 不同,SimpleNamespace 实例是可写的。这意味着您可以通过正常的属性访问添加、删除和修改命名空间。

参见

PEP 421 - 添加 sys.implementation

PEP 由 Eric Snow 撰写并实现。

使用 importlib 作为导入的实现

bpo-2377 - 将 __import__ 替换为 importlib.__import__ bpo-13959 - 在纯 Python 中重新实现 imp 的部分 bpo-14605 - 使导入机制显式化 bpo-14646 - 要求加载器设置 __loader__ 和 __package__

__import__() 函数现在由 importlib.__import__() 提供支持。这项工作导致 PEP 302 的“第二阶段”完成。这项更改带来了多项好处。首先,它允许将更多驱动导入的机制暴露出来,而不是隐式地隐藏在 C 代码中。它还为所有支持 Python 3.3 的 Python VM 提供了一个单一的实现,有助于消除导入语义中任何 VM 特定的偏差。最后,它简化了导入的维护,允许未来的增长。

对于普通用户来说,语义上应该没有可见的更改。对于那些当前操纵导入或以编程方式调用导入的代码,可能需要的代码更改已在本文档的移植 Python 代码部分中介绍。

新 API

这项工作的一个巨大好处是揭示了导入语句的工作原理。这意味着曾经隐式的各种导入器现在已完全作为 importlib 包的一部分公开。

importlib.abc 中定义的抽象基类已扩展,通过引入 importlib.abc.MetaPathFinderimportlib.abc.PathEntryFinder,正确区分了元路径查找器路径入口查找器。旧的抽象基类 importlib.abc.Finder 现在仅为向后兼容性而提供,不强制任何方法要求。

在查找器方面,importlib.machinery.FileFinder 公开了用于搜索模块源文件和字节码文件的机制。以前,这个类是 sys.path_hooks 的隐式成员。

对于加载器,新的抽象基类 importlib.abc.FileLoader 有助于编写一个使用文件系统作为模块代码存储机制的加载器。源文件加载器(importlib.machinery.SourceFileLoader)、无源字节码文件加载器(importlib.machinery.SourcelessFileLoader)和扩展模块加载器(importlib.machinery.ExtensionFileLoader)现在可以直接使用。

ImportError 现在具有 namepath 属性,当有相关数据可提供时会设置这些属性。导入失败的消息现在也将提供模块的完整名称,而不仅仅是模块名称的末尾。

importlib.invalidate_caches() 函数现在将调用 sys.path_importer_cache 中所有缓存的查找器上同名的方法,以根据需要帮助清理任何存储状态。

可见更改

有关可能需要的代码更改,请参阅移植 Python 代码一节。

除了 importlib 现在公开的范围之外,导入还有其他可见更改。最大的一点是 sys.meta_pathsys.path_hooks 现在存储导入使用的所有元路径查找器和路径入口钩子。以前,查找器是隐式的,隐藏在导入的 C 代码中,而不是直接暴露。这意味着现在可以轻松地删除或更改各种查找器的顺序以满足需求。

另一个变化是所有模块都有一个 __loader__ 属性,存储用于创建模块的加载器。PEP 302 已更新,强制加载器实现此属性,因此未来一旦第三方加载器更新,人们就可以依赖此属性的存在。不过,在此之前,导入会在加载后设置模块。

加载器现在也应该从 PEP 366 设置 __package__ 属性。同样,导入本身已经将此属性设置在 importlib 中的所有加载器上,并且导入本身正在加载后设置该属性。

当在 sys.path_hooks 上找不到查找器时,现在会将 None 插入到 sys.path_importer_cache 中。由于 imp.NullImporter 未直接暴露在 sys.path_hooks 上,因此不能再依赖它始终可用作表示未找到查找器的值。

所有其他更改都与语义更改有关,在为 Python 3.3 更新代码时应考虑这些更改,因此应在本文档的移植 Python 代码部分中阅读。

(由 Brett Cannon 实现)

其他语言更改

对核心 Python 语言做了一些较小的更改

  • 添加了对 Unicode 名称别名和命名序列的支持。unicodedata.lookup()'\N{...}' 现在都解析名称别名,unicodedata.lookup() 也解析命名序列。

    (由 Ezio Melotti 在bpo-12753 中贡献。)

  • Unicode 数据库更新到 UCD 版本 6.1.0

  • range() 对象的相等比较现在返回反映这些 range 对象生成的底层序列相等的结果。(bpo-13201

  • bytesbytearray 对象的 count()find()rfind()index()rindex() 方法现在接受 0 到 255 之间的整数作为它们的第一个参数。

    (由 Petri Lehtinen 在bpo-12170 中贡献。)

  • bytesbytearrayrjust()ljust()center() 方法现在接受 bytearray 作为 fill 参数。(由 Petri Lehtinen 在bpo-12380 中贡献。)

  • listbytearray 中添加了新方法:copy()clear()bpo-10516)。因此,MutableSequence 现在也定义了一个 clear() 方法(bpo-11388)。

  • 原始字节字面量现在可以写成 rb"..."br"..."

    (由 Antoine Pitrou 在bpo-13748 中贡献。)

  • dict.setdefault() 现在只对给定键进行一次查找,因此在使用内置类型时它是原子性的。

    (由 Filip Gruszczyński 在bpo-13521 中贡献。)

  • 当函数调用与函数签名不匹配时产生的错误消息已显著改进。

    (由 Benjamin Peterson 贡献。)

更细粒度的导入锁

以前的 CPython 版本一直依赖全局导入锁。这导致了意想不到的麻烦,例如当导入模块会副作用地触发不同线程中的代码执行时,会导致死锁。有时会采用笨拙的解决方法,例如 PyImport_ImportModuleNoBlock() C API 函数。

在 Python 3.3 中,导入模块会获取一个逐模块锁。这正确地序列化了从多个线程导入给定模块的操作(防止暴露未完全初始化的模块),同时消除了上述麻烦。

(由 Antoine Pitrou 在bpo-9260 中贡献。)

内置函数和类型

  • open() 获得了一个新的 opener 参数:文件对象的底层文件描述符通过调用 opener 和 (file, flags) 来获得。它可用于使用自定义标志,例如 os.O_CLOEXEC。添加了 'x' 模式:以独占创建模式打开,如果文件已存在则失败。

  • print():添加了 flush 关键字参数。如果 flush 关键字参数为 true,则强制刷新流。

  • hash():哈希随机化默认启用,请参阅 object.__hash__()PYTHONHASHSEED

  • str 类型获得了一个新的 casefold() 方法:返回字符串的大小写折叠副本,大小写折叠字符串可用于不区分大小写的匹配。例如,'ß'.casefold() 返回 'ss'

  • 序列文档已大幅重写,以更好地解释二进制/文本序列的区别,并为各个内置序列类型提供特定的文档部分(bpo-4966)。

新模块

faulthandler

这个新的调试模块 faulthandler 包含用于在故障(如段错误等崩溃)、超时或用户信号时显式转储 Python 追溯的函数。调用 faulthandler.enable() 可为 SIGSEGVSIGFPESIGABRTSIGBUSSIGILL 信号安装故障处理程序。您也可以通过设置 PYTHONFAULTHANDLER 环境变量或使用 -X faulthandler 命令行选项在启动时启用它们。

Linux 上分段故障的示例

$ python -q -X faulthandler
>>> import ctypes
>>> ctypes.string_at(0)
Fatal Python error: Segmentation fault

Current thread 0x00007fb899f39700:
  File "/home/python/cpython/Lib/ctypes/__init__.py", line 486 in string_at
  File "<stdin>", line 1 in <module>
Segmentation fault

ipaddress

新的 ipaddress 模块提供了用于创建和操作表示 IPv4 和 IPv6 地址、网络和接口(即与特定 IP 子网关联的 IP 地址)的对象的工具。

(由 Google 和 Peter Moody 在 PEP 3144 中贡献。)

lzma

新添加的 lzma 模块提供使用 LZMA 算法进行数据压缩和解压缩的功能,包括对 .xz.lzma 文件格式的支持。

(由 Nadeem Vawda 和 Per Øyvind Karlsen 在bpo-6715 中贡献。)

改进的模块

abc

改进了对包含与抽象方法组合的描述符的抽象基类的支持。现在,声明抽象描述符的推荐方法是提供 __isabstractmethod__ 作为动态更新的属性。内置描述符已相应更新。

(由 Darren Dale 在bpo-11610 中贡献。)

abc.ABCMeta.register() 现在返回注册的子类,这意味着它现在可以用作类装饰器(bpo-10868)。

array

array 模块支持使用 qQ 类型代码的 long long 类型。

(由 Oren Tirosh 和 Hirokazu Yamamoto 在bpo-1172711 中贡献。)

base64

base64 现代接口的解码函数现在接受仅 ASCII 的 Unicode 字符串。例如,base64.b64decode('YWJj') 返回 b'abc'。(由 Catalin Iacob 在bpo-13641 中贡献。)

binascii

除了它们通常接受的二进制对象之外,a2b_ 函数现在也都接受纯 ASCII 字符串作为输入。(由 Antoine Pitrou 在bpo-13637 中贡献。)

bz2

bz2 模块已从头重写。在此过程中,添加了几个新功能

  • 新的 bz2.open() 函数:以二进制或文本模式打开 bzip2 压缩文件。

  • bz2.BZ2File 现在可以通过其构造函数的 fileobj 参数从任意类似文件的对象读取和写入。

    (由 Nadeem Vawda 在bpo-5863 中贡献。)

  • bz2.BZ2Filebz2.decompress() 现在可以解压缩多流输入(例如 pbzip2 工具产生的输入)。bz2.BZ2File 现在也可以使用 'a'(追加)模式创建此类文件。

    (由 Nir Aides 在bpo-1625 中贡献。)

  • bz2.BZ2File 现在实现了 io.BufferedIOBase API 的所有功能,除了 detach()truncate() 方法。

codecs

mbcs 编码器已重写,以在所有 Windows 版本上正确处理 replaceignore 错误处理程序。mbcs 编码器现在支持所有错误处理程序,而不是仅支持 replace 进行编码和 ignore 进行解码。

添加了一个新的仅限 Windows 的编码器:cp65001bpo-13216)。它是 Windows 代码页 65001 (Windows UTF-8, CP_UTF8)。例如,如果控制台输出代码页设置为 cp65001(例如,使用 chcp 65001 命令),则由 sys.stdout 使用。

多字节 CJK 解码器现在重新同步更快。它们只忽略无效字节序列的第一个字节。例如,b'\xff\n'.decode('gb2312', 'replace') 现在在替换字符后返回一个 \n

bpo-12016

增量 CJK 编解码器编码器在每次调用其 encode() 方法时不再重置。例如

>>> import codecs
>>> encoder = codecs.getincrementalencoder('hz')('strict')
>>> b''.join(encoder.encode(x) for x in '\u52ff\u65bd\u65bc\u4eba\u3002 Bye.')
b'~{NpJ)l6HK!#~} Bye.'

这个例子在旧版本的 Python 中会得到 b'~{Np~}~{J)~}~{l6~}~{HK~}~{!#~} Bye.'

bpo-12100

unicode_internal 编码器已弃用。

collections

添加了一个新的 ChainMap 类,允许将多个映射视为一个单元。(由 Raymond Hettinger 为bpo-11089 编写,并在bpo-11297 中公开。)

抽象基类已移至新的 collections.abc 模块中,以更好地区分抽象集合类和具体集合类。为保留现有导入,ABCs 的别名仍存在于 collections 模块中。(bpo-11085

Counter 类现在支持一元运算符 +-,以及就地运算符 +=-=|=&=。(由 Raymond Hettinger 在bpo-13121 中贡献。)

contextlib

ExitStack 现在为上下文管理器和类似清理功能的编程操作提供了坚实的基础。与以前的 contextlib.nested API(已弃用并删除)不同,新 API 旨在无论上下文管理器是在其 __init__ 方法(例如文件对象)中还是在其 __enter__ 方法(例如 threading 模块中的同步对象)中获取资源,都能正常工作。

bpo-13585

crypt

crypt 模块中增加了 salt 和模块化加密格式(哈希方法)以及 mksalt() 函数。

bpo-10924

curses

  • 如果 curses 模块链接到 ncursesw 库,则在传递 Unicode 字符串或字符时使用 Unicode 函数(例如 waddwstr()),否则使用字节函数(例如 waddstr())。

  • 使用区域设置编码而不是 utf-8 来编码 Unicode 字符串。

  • curses.window 有一个新属性 curses.window.encoding

  • curses.window 类有一个新的 get_wch() 方法来获取一个宽字符

  • curses 模块有一个新的 unget_wch() 函数,用于推送一个宽字符,以便下一个 get_wch() 将返回它

(由 Iñigo Serna 在bpo-6755 中贡献。)

datetime

decimal

bpo-7652 - 集成快速原生十进制算术。

C 模块和 libmpdec 由 Stefan Krah 撰写。

新的十进制模块的 C 版本集成了高速的 libmpdec 库,用于任意精度正确舍入的十进制浮点算术。libmpdec 符合 IBM 的通用十进制算术规范。

性能提升范围从数据库应用程序的 10 倍到数值密集型应用程序的 100 倍。这些数字是十进制浮点算术中使用的标准精度的预期增益。由于精度是用户可配置的,因此具体数字可能会有所不同。例如,在整数大数算术中,差异可能显著更高。

下表仅供说明。基准测试可在 https://www.bytereef.org/mpdecimal/quickstart.html 获得。

decimal.py

_decimal

加速

pi

42.02 秒

0.345 秒

120 倍

电信

172.19 秒

5.68 秒

30 倍

psycopg

3.57 秒

0.29 秒

12 倍

功能

  • FloatOperation 信号可选择启用更严格的浮点数和十进制数混合语义。

  • 如果 Python 在没有线程的情况下编译,C 版本会自动禁用昂贵的线程本地上下文机制。在这种情况下,变量 HAVE_THREADS 设置为 False

API 变更

  • C 模块具有以下上下文限制,具体取决于机器架构

    32位

    64位

    MAX_PREC

    425000000

    999999999999999999

    MAX_EMAX

    425000000

    999999999999999999

    MIN_EMIN

    -425000000

    -999999999999999999

  • 在上下文模板(DefaultContextBasicContextExtendedContext)中,EmaxEmin 的量级已更改为 999999

  • decimal.py 中的 Decimal 构造函数不遵守上下文限制,并精确转换具有任意指数或精度的值。由于 C 版本具有内部限制,因此使用了以下方案:如果可能,精确转换值,否则引发 InvalidOperation 且结果为 NaN。在后一种情况下,始终可以使用 create_decimal() 来获取舍入或不精确的值。

  • decimal.py 中的幂函数始终正确舍入。在 C 版本中,它由正确舍入的 exp()ln() 函数定义,但最终结果仅是“几乎总是正确舍入”。

  • 在 C 版本中,包含信号的上下文字典是 MutableMapping。出于速度原因,flagstraps 始终指向上下文初始化时使用的同一个 MutableMapping。如果分配了新的信号字典,flagstraps 将使用新值进行更新,但它们不引用 RHS 字典。

  • 腌制 Context 会产生不同的输出,以实现 Python 和 C 版本的通用交换格式。

  • Context 构造函数中的参数顺序已更改,以匹配 repr() 显示的顺序。

  • quantize() 方法中的 watchexp 参数已弃用。

email

策略框架

email 包现在有一个 policy 框架。Policy 是一个具有多个方法和属性的对象,用于控制 email 包的行为。Python 3.3 的主要策略是 Compat32 策略,它提供了与 Python 3.2 中 email 包的向后兼容性。policy 可以在 email 消息由 parser 解析时,或创建 Message 对象时,或使用 generator 序列化 email 时指定。除非被覆盖,传递给 parser 的策略将由 parser 创建的所有 Message 对象和子对象继承。默认情况下,generator 将使用它正在序列化的 Message 对象的策略。默认策略是 compat32

所有 policy 对象实现的最小控制集是

max_line_length

Message 被序列化时,单个行的最大长度(不包括换行符)。默认为 78。

linesep

Message 被序列化时,用于分隔单个行的字符。默认为 \n

cte_type

7bit8bit8bit 仅适用于 Bytes generator,表示在协议允许的情况下(或在原始输入中存在的情况下)可以使用非 ASCII 字符。

raise_on_defect

导致 parser 在遇到缺陷时引发错误,而不是将它们添加到 Message 对象的 defects 列表中。

一个新的策略实例,具有新的设置,是通过策略对象的 clone() 方法创建的。clone 将上述任何控件作为关键字参数。任何未在调用中指定的控件都保留其默认值。因此,您可以创建使用 \r\n 换行符的策略,如下所示

mypolicy = compat32.clone(linesep='\r\n')

策略可以使您的应用程序生成所需格式的消息变得更简单。您无需记住在所有调用 generator 的地方都指定 linesep='\r\n',您可以在设置 parserMessage 使用的策略时指定一次,无论您的程序使用哪个来创建 Message 对象。另一方面,如果您需要生成多种形式的消息,您仍然可以在相应的 generator 调用中指定参数。或者您可以为不同的情况使用自定义策略实例,并在创建 generator 时传递这些实例。

带有新 Header API 的临时策略

尽管策略框架本身就很有价值,但引入它的主要动机是允许创建新策略,以一种为不使用新策略的人保持向后兼容性的方式实现 email 包的新功能。由于新策略引入了新的 API,我们将在 Python 3.3 中将其作为临时策略发布。如果核心开发人员认为有必要,可能会发生向后不兼容的更改(包括代码的删除)。

新策略是 EmailPolicy 的实例,并添加了以下附加控制

refold_source

控制由 parser 解析的头部是否由 generator 重折叠。它可以是 nonelongall。默认是 long,这意味着长度超过 max_line_length 的源头部会被重折叠。none 意味着没有行被重折叠,all 意味着所有行都被重折叠。

header_factory

一个可调用对象,它接受一个 namevalue 并生成一个自定义头部对象。

header_factory 是新策略提供新功能的关键。当使用新策略时,从 Message 对象检索到的任何头部都是由 header_factory 生成的对象,并且每次您在 Message 上设置头部时,它都会成为由 header_factory 生成的对象。所有此类头部对象都有一个等于头部名称的 name 属性。地址和日期头部具有附加属性,可让您访问头部的解析数据。这意味着您现在可以执行以下操作

>>> m = Message(policy=SMTP)
>>> m['To'] = 'Éric <foo@example.com>'
>>> m['to']
'Éric <foo@example.com>'
>>> m['to'].addresses
(Address(display_name='Éric', username='foo', domain='example.com'),)
>>> m['to'].addresses[0].username
'foo'
>>> m['to'].addresses[0].display_name
'Éric'
>>> m['Date'] = email.utils.localtime()
>>> m['Date'].datetime
datetime.datetime(2012, 5, 25, 21, 39, 24, 465484, tzinfo=datetime.timezone(datetime.timedelta(-1, 72000), 'EDT'))
>>> m['Date']
'Fri, 25 May 2012 21:44:27 -0400'
>>> print(m)
To: =?utf-8?q?=C3=89ric?= <foo@example.com>
Date: Fri, 25 May 2012 21:44:27 -0400

您会注意到,当消息被序列化时,unicode 显示名称会自动编码为 utf-8,但当直接访问头部时,您会得到 unicode 版本。这消除了处理 email.header decode_header()make_header() 函数的任何需要。

您还可以从部件创建地址

>>> m['cc'] = [Group('pals', [Address('Bob', 'bob', 'example.com'),
...                           Address('Sally', 'sally', 'example.com')]),
...            Address('Bonzo', addr_spec='bonz@laugh.com')]
>>> print(m)
To: =?utf-8?q?=C3=89ric?= <foo@example.com>
Date: Fri, 25 May 2012 21:44:27 -0400
cc: pals: Bob <bob@example.com>, Sally <sally@example.com>;, Bonzo <bonz@laugh.com>

自动解码为 unicode

>>> m2 = message_from_string(str(m))
>>> m2['to']
'Éric <foo@example.com>'

解析消息时,您可以使用头部对象的 addressesgroups 属性来访问组和单个地址

>>> m2['cc'].addresses
(Address(display_name='Bob', username='bob', domain='example.com'), Address(display_name='Sally', username='sally', domain='example.com'), Address(display_name='Bonzo', username='bonz', domain='laugh.com'))
>>> m2['cc'].groups
(Group(display_name='pals', addresses=(Address(display_name='Bob', username='bob', domain='example.com'), Address(display_name='Sally', username='sally', domain='example.com')), Group(display_name=None, addresses=(Address(display_name='Bonzo', username='bonz', domain='laugh.com'),))

总之,如果您使用新的策略之一,头部操作将按预期方式工作:您的应用程序使用 unicode 字符串,email 包透明地将 unicode 编码和解码为 RFC 标准内容传输编码。

其他 API 更改

新的 BytesHeaderParser,添加到 parser 模块中,以补充 HeaderParser 并完成 Bytes API。

新的实用函数

ftplib

  • ftplib.FTP 现在接受 source_address 关键字参数,用于在创建传出套接字时指定 (host, port) 作为 bind 调用的源地址。(由 Giampaolo Rodolà 在 bpo-8594 中贡献。)

  • FTP_TLS 类现在提供了一个新的 ccc() 函数,用于将控制通道恢复为明文。这对于利用知道如何处理非安全 FTP 的 NAT 防火墙而无需打开固定端口可能很有用。(由 Giampaolo Rodolà 在 bpo-12139 中贡献。)

  • 添加了 ftplib.FTP.mlsd() 方法,该方法提供可解析的目录列表格式,并弃用 ftplib.FTP.nlst()ftplib.FTP.dir()。(由 Giampaolo Rodolà 在 bpo-11072 中贡献。)

functools

functools.lru_cache() 装饰器现在接受 typed 关键字参数(默认为 False),以确保它将不同类型但比较相等的值缓存到单独的缓存槽中。(由 Raymond Hettinger 在 bpo-13227 中贡献。)

gc

现在可以使用新的 callbacks 列表注册在垃圾收集器收集之前和之后调用的回调。

hmac

已添加新的 compare_digest() 函数,以防止通过计时分析对摘要进行侧信道攻击。(由 Nick Coghlan 和 Christian Heimes 在 bpo-15061 中贡献。)

http

http.server.BaseHTTPRequestHandler 现在缓冲头部并在调用 end_headers() 时一次性写入。新方法 flush_headers() 可用于直接管理何时发送累积的头部。(由 Andrew Schaaf 在 bpo-3709 中贡献。)

http.server 现在生成有效的 HTML 4.01 strict 输出。(由 Ezio Melotti 在 bpo-13295 中贡献。)

http.client.HTTPResponse 现在有一个 readinto() 方法,这意味着它可以作为一个 io.RawIOBase 类使用。(由 John Kuhn 在 bpo-13464 中贡献。)

html

html.parser.HTMLParser 现在能够解析损坏的标记而不会引发错误,因此构造函数的 strict 参数和 HTMLParseError 异常已被弃用。解析损坏标记的能力是许多错误修复的结果,这些修复也适用于 Python 2.7/3.2 的最新错误修复版本。(由 Ezio Melotti 在 bpo-15114,以及 bpo-14538bpo-13993bpo-13960bpo-13358bpo-1745761bpo-755670bpo-13357bpo-12629bpo-1200313bpo-670664bpo-13273bpo-12888bpo-7311 中贡献。)

一个新的 html5 字典已添加到 html.entities 模块中,它将 HTML5 命名字符引用映射到等效的 Unicode 字符(例如 html5['gt;'] == '>')。现在 HTMLParser 也使用该字典。(由 Ezio Melotti 在 bpo-11113bpo-15156 中贡献。)

imaplib

IMAP4_SSL 构造函数现在接受 SSLContext 参数来控制安全通道的参数。

(由 Sijin Joseph 在 bpo-8808 中贡献。)

inspect

新增了 getclosurevars() 函数。此函数报告从函数体引用的所有名称的当前绑定以及这些名称的解析位置,从而更容易在测试依赖有状态闭包的代码时验证正确的内部状态。

(由 Meador Inge 和 Nick Coghlan 在 bpo-13062 中贡献。)

新增了 getgeneratorlocals() 函数。此函数报告生成器堆栈帧中局部变量的当前绑定,从而更容易在测试生成器时验证正确的内部状态。

(由 Meador Inge 在 bpo-15153 中贡献。)

io

open() 函数有一个新的 'x' 模式,可用于独占地创建一个新文件,如果文件已存在,则引发 FileExistsError。它基于 C11 ‘x’ 模式到 fopen()。

(由 David Townshend 在 bpo-12760 中贡献。)

TextIOWrapper 类的构造函数有一个新的可选参数 write_through。如果 write_throughTrue,则对 write() 的调用保证不会被缓冲:写入 TextIOWrapper 对象的任何数据都会立即处理到其底层的二进制缓冲区。

itertools

accumulate() 现在接受一个可选的 func 参数,用于提供用户提供的二进制函数。

logging

basicConfig() 函数现在支持一个可选的 handlers 参数,该参数接受一个可迭代的处理程序,用于添加到根记录器。

已在 SysLogHandler 中添加了一个类级别属性 append_nul,以允许控制 NUL (\000) 字节是否附加到 syslog 记录中,因为有些守护进程需要它,而有些则将其直接传递到日志中。

math

math 模块有一个新函数 log2(),它返回 x 的以 2 为底的对数。

(由 Mark Dickinson 在 bpo-11888 中编写。)

mmap

read() 方法现在与其他文件类对象更兼容:如果省略参数或将其指定为 None,它将返回从当前文件位置到映射末尾的字节。(由 Petri Lehtinen 在 bpo-12021 中贡献。)

multiprocessing

新的 multiprocessing.connection.wait() 函数允许以超时方式轮询多个对象(例如连接、套接字和管道)。(由 Richard Oudkerk 在 bpo-12328 中贡献。)

multiprocessing.connection.Connection 对象现在可以通过多进程连接进行传输。(由 Richard Oudkerk 在 bpo-4892 中贡献。)

multiprocessing.Process 现在接受一个 daemon 关键字参数,以覆盖从父进程继承 daemon 标志的默认行为(bpo-6064)。

新的属性 multiprocessing.Process.sentinel 允许程序使用适当的操作系统原语(例如,posix 系统上的 select)同时等待多个 Process 对象。

新的方法 multiprocessing.pool.Pool.starmap()starmap_async() 提供了与现有 multiprocessing.pool.Pool.map()map_async() 函数等效的 itertools.starmap()。(由 Hynek Schlawack 在 bpo-12708 中贡献。)

nntplib

nntplib.NNTP 类现在支持上下文管理协议,以无条件地消耗 socket.error 异常并在完成后关闭 NNTP 连接

>>> from nntplib import NNTP
>>> with NNTP('news.gmane.org') as n:
...     n.group('gmane.comp.python.committers')
...
('211 1755 1 1755 gmane.comp.python.committers', 1755, 1, 1755, 'gmane.comp.python.committers')
>>>

(由 Giampaolo Rodolà 在 bpo-9795 中贡献。)

os

pdb

现在,Tab 补全不仅适用于命令名称,也适用于其参数。例如,对于 break 命令,函数和文件名都可以补全。

(由 Georg Brandl 在 bpo-14210 中贡献)

pickle

pickle.Pickler 对象现在有一个可选的 dispatch_table 属性,允许设置每个 pickler 的缩减函数。

(由 Richard Oudkerk 在 bpo-14166 中贡献。)

pydoc

Tk GUI 和 serve() 函数已从 pydoc 模块中移除:pydoc -gserve() 已在 Python 3.2 中弃用。

re

str 正则表达式现在支持 \u\U 转义。

(由 Serhiy Storchaka 在 bpo-3665 中贡献。)

sched

  • run() 现在接受一个 blocking 参数,当设置为 false 时,该方法会执行最近到期的调度事件(如果有),然后立即返回。这在您希望在非阻塞应用程序中使用 scheduler 时很有用。(由 Giampaolo Rodolà 在 bpo-13449 中贡献。)

  • scheduler 类现在可以在多线程环境中安全使用。(由 Josiah Carlson 和 Giampaolo Rodolà 在 bpo-8684 中贡献。)

  • scheduler 类构造函数的 timefuncdelayfunct 参数现在是可选的,分别默认为 time.time()time.sleep()。(由 Chris Clark 在 bpo-13245 中贡献。)

  • enter()enterabs()argument 参数现在是可选的。(由 Chris Clark 在 bpo-13245 中贡献。)

  • enter()enterabs() 现在接受一个 kwargs 参数。(由 Chris Clark 在 bpo-13245 中贡献。)

select

Solaris 和派生平台有一个新的类 select.devpoll,用于通过 /dev/poll 实现高性能异步套接字。(由 Jesús Cea Avión 在 bpo-6397 中贡献。)

shlex

以前未文档化的辅助函数 quote 已从 pipes 模块移至 shlex 模块并已文档化。quote() 正确地转义字符串中所有可能被 shell 赋予特殊含义的字符。

shutil

  • 新函数

    • disk_usage():提供磁盘总空间、已用空间和可用空间统计信息。(由 Giampaolo Rodolà 在 bpo-12442 中贡献。)

    • chown():允许更改给定路径的用户和/或组,也可以指定用户/组名,而不仅仅是它们的数字ID。(由 Sandro Tosi 在 bpo-12191 中贡献。)

    • shutil.get_terminal_size():返回解释器所连接的终端窗口的大小。(由 Zbigniew Jędrzejewski-Szmek 在 bpo-13609 中贡献。)

  • copy2()copystat() 现在在支持的平台上以纳秒精度保留文件时间戳。它们还在 Linux 上保留文件“扩展属性”。(由 Larry Hastings 在 bpo-14127bpo-15238 中贡献。)

  • 现在有几个函数接受可选的 symlinks 参数:当该参数为 True 时,符号链接不会被解除引用,而是对符号链接本身执行操作(如果相关,则创建一个)。(由 Hynek Schlawack 在 bpo-12715 中贡献。)

  • 将文件复制到不同的文件系统时,move() 现在像 posix mv 命令那样处理符号链接,重新创建符号链接而不是复制目标文件内容。(由 Jonathan Niehof 在 bpo-9993 中贡献。) move() 现在也将其结果返回为 dst 参数。

  • rmtree() 现在对支持 os.open()os.unlink() 中新 dir_fd 参数的平台上的符号链接攻击具有抵抗力。(由 Martin von Löwis 和 Hynek Schlawack 在 bpo-4489 中贡献。)

信号

smtpd

smtpd 模块现在支持 RFC 5321(扩展 SMTP)和 RFC 1870(大小扩展)。根据标准,这些扩展仅在客户端使用 EHLO 命令启动会话时才启用。

(初始 ELHO 支持由 Alberto Trevino 贡献。大小扩展由 Juhana Jauhiainen 贡献。补丁的实质性额外工作由 Michele Orrù 和 Dan Boswell 贡献。 bpo-8739

smtplib

SMTPSMTP_SSLLMTP 类现在接受 source_address 关键字参数,用于在创建出站套接字时在绑定调用中指定用作源地址的 (host, port)。(由 Paulo Scardine 在 bpo-11281 中贡献。)

SMTP 现在支持上下文管理协议,允许在 with 语句中使用 SMTP 实例。(由 Giampaolo Rodolà 在 bpo-11289 中贡献。)

SMTP_SSL 构造函数和 starttls() 方法现在接受 SSLContext 参数来控制安全通道的参数。(由 Kasun Herath 在 bpo-8809 中贡献。)

socket

socketserver

BaseServer 现在有一个可重写的方法 service_actions(),它由 serve_forever() 方法在服务循环中调用。ForkingMixIn 现在使用它来清理僵尸子进程。(由 Justin Warkentin 在 bpo-11109 中贡献。)

sqlite3

新的 sqlite3.Connection 方法 set_trace_callback() 可用于捕获 sqlite 处理的所有 sql 命令的跟踪。(由 Torsten Landschoff 在 bpo-11688 中贡献。)

ssl

  • ssl 模块有两个新的随机生成函数

    • RAND_bytes():生成加密强度高的伪随机字节。

    • RAND_pseudo_bytes():生成伪随机字节。

    (由 Victor Stinner 在 bpo-12049 中贡献。)

  • ssl 模块现在公开了更细粒度的异常层次结构,以便更容易检查各种错误。(由 Antoine Pitrou 在 bpo-11183 中贡献。)

  • load_cert_chain() 现在接受一个 password 参数,用于在私钥加密时使用。(由 Adam Simpkins 在 bpo-12803 中贡献。)

  • 通过 load_dh_params()set_ecdh_curve() 方法,现在支持 Diffie-Hellman 密钥交换,包括常规和基于椭圆曲线的密钥交换。(由 Antoine Pitrou 在 bpo-13626bpo-13627 中贡献。)

  • SSL 套接字有一个新的 get_channel_binding() 方法,允许实现某些身份验证机制,例如 SCRAM-SHA-1-PLUS。(由 Jacek Konieczny 在 bpo-12551 中贡献。)

  • 您可以通过 SSL 套接字的新 compression() 方法查询 SSL 套接字使用的 SSL 压缩算法。新属性 OP_NO_COMPRESSION 可用于禁用压缩。(由 Antoine Pitrou 在 bpo-13634 中贡献。)

  • 已添加对使用 ssl.SSLContext.set_npn_protocols() 方法的下一协议协商扩展的支持。(由 Colin Marc 在 bpo-14204 中贡献。)

  • 由于 libraryreason 属性,现在可以更轻松地检查 SSL 错误。(由 Antoine Pitrou 在 bpo-14837 中贡献。)

  • get_server_certificate() 函数现在支持 IPv6。(由 Charles-François Natali 在 bpo-11811 中贡献。)

  • 新属性 OP_CIPHER_SERVER_PREFERENCE 允许将 SSLv3 服务器套接字设置为使用服务器的密码排序偏好,而不是客户端的偏好(bpo-13635)。

stat

未文档化的 tarfile.filemode 函数已移至 stat.filemode()。它可用于将文件模式转换为 ' -rwxrwxrwx' 形式的字符串。

(由 Giampaolo Rodolà 在 bpo-14807 中贡献。)

struct

struct 模块现在通过新代码 nN 分别支持 ssize_tsize_t。(由 Antoine Pitrou 在 bpo-3163 中贡献。)

subprocess

命令字符串现在可以是 posix 平台上的字节对象。(由 Victor Stinner 在 bpo-8513 中贡献。)

新常量 DEVNULL 允许以平台无关的方式抑制输出。(由 Ross Lagerwall 在 bpo-5870 中贡献。)

sys

sys 模块有一个新的 thread_info 命名元组,用于保存有关线程实现的信息(bpo-11223)。

tarfile

tarfile 现在通过 lzma 模块支持 lzma 编码。(由 Lars Gustäbel 在 bpo-5689 中贡献。)

tempfile

tempfile.SpooledTemporaryFiletruncate() 方法现在接受 size 参数。(由 Ryan Kelly 在 bpo-9957 中贡献。)

textwrap

textwrap 模块有一个新的 indent() 函数,可以方便地为文本块中选定的行添加通用前缀(bpo-13857)。

threading

threading.Conditionthreading.Semaphorethreading.BoundedSemaphorethreading.Eventthreading.Timer,所有这些曾经是返回类实例的工厂函数,现在都是类并且可以被子类化。(由 Éric Araujo 在 bpo-10968 中贡献。)

threading.Thread 构造函数现在接受 daemon 关键字参数,以覆盖从父线程继承 daemon 标志值的默认行为(bpo-6064)。

以前的私有函数 _thread.get_ident 现在作为公共函数 threading.get_ident() 可用。这消除了 stdlib 中对 _thread 模块的几个直接访问情况。使用 _thread.get_ident 的第三方代码也应更改为使用新的公共接口。

时间

PEP 418time 模块中添加了新函数

  • get_clock_info():获取时钟信息。

  • monotonic():单调时钟(不能倒退),不受系统时钟更新影响。

  • perf_counter():具有最高可用分辨率的性能计数器,用于测量短持续时间。

  • process_time():当前进程的系统和用户 CPU 时间的总和。

其他新函数

为了提高跨平台的一致性,sleep() 现在在传递负睡眠值时会引发 ValueError。以前,这在 posix 上是一个错误,但在 Windows 上会产生无限睡眠。

types

添加一个新的 types.MappingProxyType 类:映射的只读代理。(bpo-14386

新函数 types.new_class()types.prepare_class() 为符合 PEP 3115 的动态类型创建提供支持。(bpo-14588

unittest

assertRaises()assertRaisesRegex()assertWarns()assertWarnsRegex() 现在在用作上下文管理器时接受关键字参数 msg。(由 Ezio Melotti 和 Winston Ewert 在 bpo-10775 中贡献。)

unittest.TestCase.run() 现在返回 TestResult 对象。

urllib

Request 类现在接受一个 method 参数,该参数由 get_method() 用于确定应使用哪种 HTTP 方法。例如,这将发送一个 'HEAD' 请求

>>> urlopen(Request('https://pythonlang.cn', method='HEAD'))

bpo-1673007

webbrowser

webbrowser 模块支持更多“浏览器”:Google Chrome(根据版本和操作系统命名为 chromechromiumchrome-browserchromium-browser),以及来自 FreeDesktop.org 项目的通用启动器 xdg-open 和 GNOME 3 的默认 URI 处理程序 gvfs-open。(前者由 Arnaud Calmettes 在 bpo-13620 中贡献,后者由 Matthias Klose 在 bpo-14493 中贡献。)

xml.etree.ElementTree

xml.etree.ElementTree 模块现在默认导入其 C 加速器;不再需要显式导入 xml.etree.cElementTree(此模块出于向后兼容性而保留,但现在已弃用)。此外,Elementiter 系列方法已得到优化(用 C 重写)。该模块的文档也得到了极大改进,增加了示例和更详细的参考。

zlib

新属性 zlib.Decompress.eof 使区分格式正确的压缩流和不完整或截断的压缩流成为可能。(由 Nadeem Vawda 在 bpo-12646 中贡献。)

新属性 zlib.ZLIB_RUNTIME_VERSION 报告运行时加载的底层 zlib 库的版本字符串。(由 Torsten Landschoff 在 bpo-12306 中贡献。)

优化

已添加主要的性能增强

  • 由于 PEP 393,对 Unicode 字符串的一些操作已得到优化

    • 内存占用根据文本减少 2 到 4 倍

    • 将 ASCII 字符串编码为 UTF-8 不再需要编码字符,UTF-8 表示与 ASCII 表示共享

    • UTF-8 编码器已优化

    • 重复单个 ASCII 字母并获取 ASCII 字符串的子字符串快 4 倍

  • UTF-8 现在快 2 到 4 倍。UTF-16 编码现在快达 10 倍。

    (由 Serhiy Storchaka 贡献,bpo-14624bpo-14738bpo-15026。)

构建和 C API 更改

Python 的构建过程和 C API 的更改包括

已弃用

不支持的操作系统

由于缺乏维护者,不再支持 OS/2 和 VMS。

由于维护负担,不再支持 Windows 2000 和将 COMSPEC 设置为 command.com 的 Windows 平台。

OSF 支持已在 3.2 中弃用,现已完全删除。

已弃用的 Python 模块、函数和方法

已弃用的 C API 函数和类型

Py_UNICODE 已被 PEP 393 弃用,并将在 Python 4 中删除。所有使用此类型的函数均已弃用

使用 Py_UNICODEPy_UNICODE* 类型的 Unicode 函数和方法

操纵 Py_UNICODE* 字符串的函数和宏

编码器

已弃用的功能

array 模块的 'u' 格式代码现在已弃用,并将在 Python 4 中与其余(Py_UNICODE)API 一起删除。

移植到 Python 3.3

本节列出了前面描述过的变更以及其他可能需要修改代码的 bug 修复。

移植 Python 代码

  • 哈希随机化默认启用。将 PYTHONHASHSEED 环境变量设置为 0 以禁用哈希随机化。另请参阅 object.__hash__() 方法。

  • bpo-12326:在 Linux 上,sys.platform 不再包含主版本。它现在始终是 'linux',而不是 'linux2' 或 'linux3',具体取决于用于构建 Python 的 Linux 版本。将 sys.platform == 'linux2' 替换为 sys.platform.startswith('linux'),或者如果您不需要支持旧版 Python,则直接使用 sys.platform == 'linux'。

  • bpo-13847bpo-14180timedatetime:如果时间戳超出范围,现在会引发 OverflowError 而不是 ValueError。如果 C 函数 gmtime()localtime() 失败,现在会引发 OSError

  • import 使用的默认查找器现在利用了特定目录中包含内容的缓存。如果您创建 Python 源文件或无源字节码文件,请务必调用 importlib.invalidate_caches() 以清除查找器的缓存,以便它们注意到新文件。

  • ImportError 现在使用尝试导入的模块的完整名称。检查 ImportError 消息的 doctest 将需要更新为使用模块的完整名称,而不仅仅是名称的尾部。

  • __import__()index 参数现在默认为 0 而不是 -1,并且不再支持负值。这是在实现 PEP 328 时的一个疏忽,默认值仍为 -1。如果您需要继续执行相对导入,然后执行绝对导入,则使用索引 1 执行相对导入,然后使用索引 0 执行另一个导入。但是,建议您使用 importlib.import_module(),而不是直接调用 __import__()

  • __import__() 不再允许对顶级模块使用除 0 以外的索引值。例如,__import__('sys', level=1) 现在是一个错误。

  • 由于 sys.meta_pathsys.path_hooks 默认带有查找器,您很可能希望使用 list.insert() 而不是 list.append() 将元素添加到这些列表中。

  • 由于 None 现在已插入 sys.path_importer_cache 中,如果您正在清除字典中没有查找器的路径条目,您将需要删除与 None imp.NullImporter 值配对的键,以实现向后兼容。这将在旧版 Python 上导致额外的开销,因为它们会重新将 None 插入 sys.path_importer_cache 中,其中它表示使用隐式查找器,但从语义上讲,它不应改变任何东西。

  • importlib.abc.Finder 不再指定必须实现的 find_module() 抽象方法。如果您依赖子类实现该方法,请务必先检查该方法是否存在。但是,在处理 路径入口查找器 的情况下,您可能希望首先检查 find_loader()

  • pkgutil 已转换为在内部使用 importlib。这消除了许多边缘情况,其中 PEP 302 导入模拟的旧行为未能与真实导入系统的行为匹配。导入模拟本身仍然存在,但现在已弃用。pkgutil.iter_importers()pkgutil.walk_packages() 函数对标准导入钩子进行特殊处理,因此即使它们不提供非标准的 iter_modules() 方法,它们仍然受支持。

  • 解析由 email.header.decode_header() 执行的 RFC 合规性长期存在的错误(bpo-1079)已修复。使用标准惯用语将编码标头转换为 unicode 的代码(str(make_header(decode_header(h)))不会发生变化,但查看 decode_header 返回的单个元组的代码将看到现在在 ASCII 部分之前或之后的空白已包含在 ASCII 部分中。使用 make_header 构建标头的代码也应继续工作而无需更改,因为如果输入字符串中不存在空白,make_header 会继续在 ASCII 和非 ASCII 部分之间添加空白。

  • email.utils.formataddr() 现在在传递非 ASCII 显示名称时执行正确的内容传输编码。任何依赖于之前错误行为(即保留格式化输出字符串中的非 ASCII unicode)的代码都需要更改(bpo-1690608)。

  • poplib.POP3.quit() 现在可能像所有其他 poplib 方法一样引发协议错误。如果特定应用程序在 quit 上遇到错误,则假定 quit 不会引发 poplib.error_proto 错误的代码可能需要更改(bpo-11291)。

  • 自 Python 2.4 起已弃用的 email.parser.Parserstrict 参数最终已被删除。

  • 已弃用的方法 unittest.TestCase.assertSameElements 已删除。

  • 已弃用的变量 time.accept2dyear 已删除。

  • Context._clamp 属性已从 decimal 模块中删除。它以前已被公共属性 clamp 替换。(参见 bpo-8540。)

  • 未文档化的内部帮助程序类 SSLFakeFile 已从 smtplib 中删除,因为其功能长期以来已由 socket.socket.makefile() 直接提供。

  • 在 Windows 上向 time.sleep() 传递负值现在会引发错误,而不是永远休眠。在 posix 上,它一直会引发错误。

  • ast.__version__ 常量已删除。如果您需要根据 AST 版本做出决策,请使用 sys.version_info 来做出决策。

  • 以前通过子类化私有类来解决 threading 模块使用工厂函数的事实的代码将需要更改为子类化现在公开的类。

  • threading 模块中未文档化的调试机制已被删除,从而简化了代码。这应该不会对生产代码产生影响,但在此提及,以防任何应用程序调试框架与它进行交互(bpo-13550)。

移植 C 代码

  • 在缓冲区 API 更改的过程中,Py_buffer 结构体中未文档化的 smalltable 成员已删除,并且 PyMemoryViewObject 的布局已更改。

    所有依赖 memoryobject.hobject.h 中相关部分的扩展都必须重建。

  • 由于 PEP 393Py_UNICODE 类型和所有使用此类型的函数均已弃用(但至少在五年内仍然可用)。如果您一直使用低级 Unicode API 来构造和访问 unicode 对象,并且您想受益于 PEP 393 提供的内存占用减少,您必须将代码转换为新的 Unicode API

    但是,如果您只使用过高级函数,例如 PyUnicode_Concat()PyUnicode_Join()PyUnicode_FromFormat(),您的代码将自动利用新的 unicode 表示。

  • PyImport_GetMagicNumber() 现在在失败时返回 -1

  • 由于 __import__()level 参数的负值不再有效,PyImport_ImportModuleLevel() 也如此。这也意味着 PyImport_ImportModuleEx() 使用的 level 值现在是 0 而不是 -1

构建 C 扩展

  • C 扩展的可能文件名范围已缩小。非常少见的拼写已被抑制:在 POSIX 下,名为 xxxmodule.soxxxmodule.abi3.soxxxmodule.cpython-*.so 的文件不再被识别为实现 xxx 模块。如果您一直在生成此类文件,则必须切换到其他拼写(即,从文件名中删除 module 字符串)。

    (在 bpo-14040 中实现。)

命令行开关更改

  • -Q 命令行标志和相关遗留物已删除。检查 sys.flags.division_warning 的代码需要更新。

    bpo-10998,由 Éric Araujo 贡献。)

  • python-S 启动时,import site 将不再向模块搜索路径添加特定于站点的路径。在以前的版本中,它会添加。

    bpo-11591,由 Carl Meyer 贡献,Éric Araujo 编辑。)