Python 3.3 的新特性 — Python 文档

来自菜鸟教程
Python/docs/3.7/whatsnew/3.3
跳转至:导航、​搜索

Python 3.3 中的新功能

本文解释了 Python 3.3 中与 3.2 相比的新特性。 Python 3.3 于 2012 年 9 月 29 日发布。 有关完整详细信息,请参阅 变更日志

也可以看看

PEP 398 - Python 3.3 发布时间表


摘要 – 发布亮点

新的语法特性:

  • 用于 生成器委托 的新 yield from 表达式。
  • [[Python/docs/3.7/library/stdtypes#str|]] 对象再次接受 u'unicode' 语法。

新的库模块:

新的内置功能:

实施改进:

显着改进的库模块:

安全改进:

  • 默认情况下启用哈希随机化。

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


PEP 405:虚拟环境

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

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

也可以看看

PEP 405 - Python 虚拟环境
卡尔·迈耶 (Carl Meyer) 编写的 PEP; 由 Carl Meyer 和 Vinay Sajip 实施


PEP 420:隐式命名空间包

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

也可以看看

PEP 420 - 隐式命名空间包
PEP 由 Eric V 编写。 史密斯; 由 Eric V 实施 史密斯和巴里华沙


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

PEP 3118 的实现得到了显着改进。

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

memoryview 对象现在有一个符合 PEP-3118 的 getbufferproc() 来检查消费者的请求类型。 添加了许多新功能,其中大多数功能完全适用于非连续数组和具有子偏移量的数组。

文件已更新,明确规定了出口商和消费者的责任。 缓冲区请求标志分为基本标志和复合标志。 解释了非连续和多维 NumPy 样式数组的内存布局。

特征

  • 现在支持 struct 模块语法中的所有本机单字符格式说明符(可选地以“@”为前缀)。
  • 有一些限制, cast() 方法允许更改 C 连续数组的格式和形状。
  • 任何数组类型都支持多维列表表示。
  • 任何数组类型都支持多维比较。
  • 具有格式 B、b 或 c 的可散列(只读)类型的一维内存视图现在是可散列的。 (由 Antoine Pitrou 在 中提供:issue:`13411`。)
  • 支持任意一维数组类型的切片。 例如,现在可以通过使用负步来反转 O(1) 中的内存视图。


API 更改

  • 最大维度数被官方限制为 64。
  • 空形状、步幅和子偏移的表示现在是一个空元组,而不是 None
  • 访问格式为“B”(无符号字节)的 memoryview 元素现在返回一个整数(根据 struct 模块语法)。 要返回字节对象,必须先将视图强制转换为 'c'。
  • 内存视图比较现在使用操作数的逻辑结构并按值比较所有数组元素。 支持 struct 模块语法中的所有格式字符串。 具有无法识别的格式字符串的视图仍然被允许,但无论视图内容如何,都将始终比较为不相等。
  • 有关进一步的更改,请参阅 构建和 C API 更改移植 C 代码

(由 Stefan Krah 在 :issue:`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)。 窄构建和宽构建之间的区别不再存在,即使在 Windows 下,Python 现在也表现得像宽构建。
  • 随着窄构建的消亡,窄构建特有的问题也得到了修复,例如:
    • len() 现在总是为非 BMP 字符返回 1,所以 len('\U0010FFFF') == 1;
    • 代理对不会在字符串文字中重新组合,因此 '\uDBFF\uDFFF' != '\U0010FFFF';
    • 索引或切片非 BMP 字符返回预期值,因此 '\U0010FFFF'[0] 现在返回 '\U0010FFFF' 而不是 '\uDBFF'
    • 标准库中的所有其他函数现在可以正确处理非 BMP 代码点。
  • sys.maxunicode 的值现在总是 1114111(十六进制的 0x10FFFF)。 PyUnicode_GetMax() 函数仍返回 0xFFFF0x10FFFF 以实现向后兼容性,并且不应与新的 Unicode API 一起使用(请参阅 :issue:`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 基准测试中,Python 3.3 的内存使用量比 Python 3.2 小两到三倍,并且比 Python 2.7 好一点(有关详细信息,请参阅 PEP)。

也可以看看

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 遵循与隐式启动脚本相同的版本选择规则,但可以通过传递适当的参数来选择更具体的版本(例如 -3 在还安装了 Python 2 时请求 Python 3,或 -2.6 在安装较新版本时专门请求较早的 Python 版本)。

除了启动程序,Windows 安装程序现在还包含一个选项,用于将新安装的 Python 添加到系统 PATH。 (由 Brian Curtin 在 :issue:`3561` 中贡献。)

也可以看看

PEP 397 - 适用于 Windows 的 Python 启动器
PEP 由 Mark Hammond 和 Martin v. 洛维斯; 由 Vinay Sajip 实施。

启动器文档:适用于 Windows 的 Python 启动器

安装程序PATH修改:查找Python可执行文件


PEP 3151:重新设计 OS 和 IO 异常层次结构

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

您不必再担心在 OSErrorIOErrorEnvironmentErrorWindowsErrormmap.errorsocket.errorselect.error。 所有这些异常类型现在只有一种:OSError。 出于兼容性原因,其他名称保留为别名。

此外,现在更容易捕获特定的错误情况。 无需检查来自 errno 模块的特定常量的 errno 属性(或 args[0]),您可以捕获足够的 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 - 重新设计 OS 和 IO 异常层次结构
由 Antoine Pitrou 编写和实施的 PEP


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 文字

为了简化从 Python 2 过渡到大量使用 Unicode 文字的 Unicode 感知 Python 应用程序,Python 3.3 再次支持字符串文字的“u”前缀。 这个前缀在 Python 3 中没有语义意义,提供它只是为了减少迁移到 Python 3 的纯机械变化的数量,使开发人员更容易关注更重要的语义变化(例如更严格的二进制默认分离和文本数据)。

也可以看看

PEP 414 - 显式 Unicode 文字
由 Armin Ronacher 编写的 PEP。


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 来控制模块的缓存行为。

简单命名空间

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

也可以看看

PEP 421 - 添加 sys.implementation
PEP 由 Eric Snow 编写和实施。


使用 importlib 作为导入的实现

:issue:`2377` - 用 importlib.__import__ 替换 __import__ :issue:`13959` - 在纯 Python 中重新实现部分 imp ]:issue:`14605` - 明确导入机器 :issue:`14646` - 要求加载器设置 __loader__ 和 __package__

__import__() 函数现在由 importlib.__import__() 提供支持。 这项工作导致 PEP 302 的“第 2 阶段”的完成。 这种变化有很多好处。 首先,它允许更多的机器驱动导入被公开,而不是被隐式和隐藏在 C 代码中。 它还为所有支持 Python 3.3 的 Python VM 提供了单一实现,有助于结束导入语义中任何特定于 VM 的偏差。 最后,它简化了进口的维护,允许未来的增长。

对于普通用户来说,语义上应该没有明显的变化。 对于那些当前以编程方式操作 import 或调用 import 的代码的人,可能需要的代码更改包含在本文档的 移植 Python 代码 部分中。

新 API

这项工作的一大好处是暴露了使导入语句起作用的内容。 这意味着曾经隐含的各种导入器现在作为 importlib 包的一部分完全公开。

importlib.abc 中定义的抽象基类已经扩展到通过引入 importlib.abc 来正确描述 元路径查找器路径入口查找器 。 MetaPathFinder 和 importlib.abc.PathEntryFinder,分别。 importlib.abc.Finder 的旧 ABC 现在仅用于向后兼容,不强制执行任何方法要求。

在查找器方面,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 已经更新,强制加载器实现这个属性,所以将来一旦 3rd-party loader 更新,人们将能够依赖属性。 不过,在此之前,import 会在加载后设置模块。

现在,加载器还需要设置 PEP 366 中的 __package__ 属性。 再一次, import 本身已经在所有来自 importlib 的加载器上设置了这个,并且 import 本身正在设置 post-load 属性。

None 现在插入 sys.path_importer_cachesys.path_hooks 上没有发现者时。 由于 imp.NullImporter 没有直接暴露在 sys.path_hooks 上,因此不能再依赖它始终可用作表示未找到发现者的值。

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

(由 Brett Cannon 实施)


其他语言更改

对核心 Python 语言进行的一些较小更改是:


更细粒度的导入锁

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

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

(由 Antoine Pitrou 在 中提供:issue:`9260`。)


内置函数和类型

  • open() 获取新的 opener 参数:然后通过调用 opener with (file , 标志 )。 例如,它可用于使用自定义标志,例如 os.O_CLOEXEC。 添加了 'x' 模式:打开独占创建,如果文件已经存在则失败。
  • print():添加了 flush 关键字参数。 如果 flush 关键字参数为 true,则强制刷新流。
  • hash():默认启用哈希随机化,参见 object.__hash__()PYTHONHASHSEED
  • str 类型获得了一个新的 casefold() 方法:返回字符串的 casefolded 副本,casefolded 字符串可用于无 case 匹配。 例如,'ß'.casefold() 返回 'ss'
  • 序列文档已被大量重写,以更好地解释二进制/文本序列的区别,并为各个内置序列类型提供特定的文档部分 (:issue:`4966`)。


新模块

故障处理程序

这个新的调试模块 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

IP地址

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

(由 Google 和 Peter Moody 在 PEP 3144 中提供。)


lzma

新增的 lzma 模块提供了使用 LZMA 算法的数据压缩和解压,包括对 .xz.lzma 文件格式的支持。

(由 Nadeem Vawda 和 Per Øyvind Karlsen 在 中提供:issue:`6715`。)


改进的模块

美国广播公司

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


(由 Darren Dale 在 中提供:问题:`11610`。)

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


大批

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

(由 Oren Tirosh 和 Hirokazu Yamamoto 在 中提供:issue:`1172711`。)


base64

base64 现代接口的解码功能现在接受仅 ASCII 的 Unicode 字符串。 例如,base64.b64decode('YWJj') 返回 b'abc'。 (由 Catalin Iacob 在 :issue:`13641` 中提供。)


二进制文件

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


bz2

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


编解码器

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

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

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

:问题:`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.'

:问题:`12100`

unicode_internal 编解码器已被弃用。


收藏

添加新的 ChainMap 类,以允许将多个映射视为一个单元。 (由 Raymond Hettinger 为 :issue:`11089` 撰写,在 :issue:`11297` 中公开。)

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

Counter 类现在支持一元 +- 运算符,以及就地运算符 +=-=|=&=。 (由 Raymond Hettinger 在 中提供:issue:`13121`。)


上下文库

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

:问题:`13585`


地穴

crypt 模块添加盐和模块化 crypt 格式(散列方法)和 mksalt() 函数。

:问题:`10924`


诅咒

  • 如果 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 在 :issue:`6755` 中贡献。)


约会时间


十进制

:issue:`7652` - 集成快速原生十进制算法。
C-module 和 libmpdec 由 Stefan Krah 编写。

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

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

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

十进制.py _十进制 加速
圆周率 42.02s 0.345s 120倍
电信公司 172.19s 5.68s 30倍
心理咨询师 3.57s 0.29s 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 参数已弃用。


电子邮件

政策框架

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

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

最大行长度 Message 被序列化时,单个行可能具有的最大长度,不包括linesep 字符。 默认为 78。
线 序列化 Message 时用于分隔各行的字符。 默认为 \n
cte_type 7bit8bit8bit 仅适用于 Bytes generator,这意味着可以在协议允许的地方(或在原始输入中存在的地方)使用非 ASCII。
raise_on_defect 当遇到缺陷而不是将它们添加到 Message 对象的 defects 列表时,导致 parser 引发错误。


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

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

策略可用于简化应用程序所需格式的消息生成。 不必记住在所有称为 generator 的地方都指定 linesep='\r\n',您可以指定一次,当您设置 parser 或 [ X169X],无论您的程序使用哪个来创建 Message 对象。 另一方面,如果您需要生成多种形式的消息,您仍然可以在适当的 generator 调用中指定参数。 或者,您可以为不同的案例定制策略实例,并在创建 generator 时将其传入。


带有新标头 API 的临时政策

虽然策略框架本身是值得的,但引入它的主要动机是允许创建新策略,以一种为不使用新策略的人保持向后兼容性的方式为电子邮件包实施新功能。 由于新政策引入了新的 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 字符串,并且电子邮件包透明地对 unicode 与 RFC 标准内容传输编码进行编码和解码。


其他 API 更改

新增 BytesHeaderParser,添加到 parser 模块以补充 HeaderParser 并完善 Bytes API。

新的实用功能:


ftplib


功能工具

functools.lru_cache() 装饰器现在接受 typed 关键字参数(默认为 False 以确保它缓存不同类型的值,这些值在不同的缓存槽中比较相等. (由 Raymond Hettinger 在 中提供:issue:`13227`。)


GC

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


海马

添加了新的 compare_digest() 函数,以防止通过时序分析对摘要进行侧信道攻击。 (由 Nick Coghlan 和 Christian Heimes 在 :issue:`15061` 中提供。)


http

http.server.BaseHTTPRequestHandler 现在缓冲标头并在调用 end_headers() 时一次性写入所有标头。 一个新的方法 flush_headers() 可用于直接管理何时发送累积的标头。 (由 Andrew Schaaf 在 :issue:`3709` 中提供。)

http.server 现在产生有效的 HTML 4.01 strict 输出。 (由 Ezio Melotti 在 中提供:issue:`13295`。)

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


html

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

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


映射库

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

(由 Sijin Joseph 在 中提供:issue:`8808`。)


检查

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

(由 Meador Inge 和 Nick Coghlan 在 :issue:`13062` 中贡献。)

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

(由 Meador Inge 在 中提供:issue:`15153`。)


io

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

(由 David Townshend 在 中提供:issue:`12760`。)

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


迭代工具

accumulate() 现在采用可选的 func 参数来提供用户提供的二进制函数。


日志记录

basicConfig() 函数现在支持可选的 handlers 参数,该参数将可迭代的处理程序添加到根记录器中。

类级别属性 append_nul 已添加到 SysLogHandler 以允许控制将 NUL (\000) 字节附加到系统日志记录,因为对于有些守护进程需要它,而对于其他守护进程,它被传递到日志中。


数学

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

(由 Mark Dickinson 在 :issue:`11888` 中撰写。)


映射

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


多处理

新的 multiprocessing.connection.wait() 函数允许使用超时轮询多个对象(例如连接、套接字和管道)。 (由 Richard Oudkerk 在 :issue:`12328` 中提供。)

multiprocessing.Connection 对象现在可以通过多处理连接传输。 (由 Richard Oudkerk 在 :issue:`4892` 中提供。)

multiprocessing.Process 现在接受 daemon 关键字参数来覆盖从父进程继承 daemon 标志的默认行为 (:issue:`6064`[ X182X])。

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

新方法 multiprocessing.pool.Pool.starmap()starmap_async() 提供与现有 multiprocessing.pool 等效的 itertools.starmap()。 Pool.map() 和 map_async() 函数。 (由 Hynek Schlawack 在 :issue:`12708` 中提供。)


ntplib

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à 在 :issue:`9795` 中提供。)


操作系统


数据库

制表符完成现在不仅可用于命令名称,还可用于它们的参数。 例如,对于break命令,函数名和文件名就完成了。

(由 Georg Brandl 在 中提供:issue:`14210`


泡菜

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

(由 Richard Oudkerk 在 :issue:`14166` 中提供。)


pydoc

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


关于

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

(由 Serhiy Storchaka 在 中提供:issue:`3665`。)


计划


选择

Solaris 和衍生平台有一个新类 select.devpoll,用于通过 /dev/poll 实现高性能异步套接字。 (由 Jesús Cea Avión 在 :issue:`6397` 中提供。)


shlex

来自 pipes 模块的先前未记录的辅助函数 quote 已移至 shlex 模块并记录在案。 quote() 正确转义字符串中的所有字符,否则 shell 可能会赋予这些字符特殊含义。


休蒂尔

  • 新功能:
  • copy2()copystat() 现在在支持它的平台上以纳秒精度保存文件时间戳。 它们还在 Linux 上保留文件“扩展属性”。 (由 Larry Hastings 在 :issue:`14127`:issue:`15238` 中贡献。)
  • 几个函数现在采用一个可选的 symlinks 参数:当该参数为真时,符号链接不会取消引用,而是操作对符号链接本身起作用(或创建一个,如果相关)。 (由 Hynek Schlawack 在 :issue:`12715` 中提供。)
  • 将文件复制到不同的文件系统时,move() 现在以 posix mv 命令的方式处理符号链接,重新创建符号链接而不是复制目标文件内容。 (由 Jonathan Niehof 在 中贡献:issue:`9993`。)move() 现在也返回 dst 参数作为其结果。
  • rmtree() 现在可以抵抗支持 os.open() 和 os.unlink()[ 中的新 dir_fd 参数的平台上的符号链接攻击X150X]。 (由 Martin von Löwis 和 Hynek Schlawack 在 :issue:`4489` 中提供。)


信号


smtpd

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

(Alberto Trevino 最初支持 ELHO。 Juhana Jauhiainen 的尺寸扩展。 Michele Orrù 和 Dan Boswell 对补丁进行了大量额外工作。 :问题:`8739`)


smtplib

SMTPSMTP_SSLLMTP 类现在接受 source_address 关键字参数来指定 (host, port) 用作创建传出套接字时绑定调用中的源地址。 (由 Paulo Scardine 在 :issue:`11281` 中提供。)

SMTP 现在支持上下文管理协议,允许在 with 语句中使用 SMTP 实例。 (由 Giampaolo Rodolà 在 中提供:issue:`11289`。)

SMTP_SSL 构造函数和 starttls() 方法现在接受 SSLContext 参数来控制安全通道的参数。 (由 Kasun Herath 在 中提供:issue:`8809`。)


插座


套接字服务器

BaseServer 现在有一个可覆盖的方法 service_actions(),由服务循环中的 serve_forever() 方法调用。 ForkingMixIn 现在使用它来清理僵尸子进程。 (由 Justin Warkentin 在 中提供:issue:`11109`。)


sqlite3

新的 sqlite3.Connection 方法 set_trace_callback() 可用于捕获由 sqlite 处理的所有 sql 命令的跟踪。 (由 Torsten Landschoff 在 中提供:issue:`11688`。)


ssl


状态

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

(由 Giampaolo Rodolà 在 中提供:issue:`14807`。)


结构

struct 模块现在分别通过新代码 nN 支持 ssize_tsize_t。 (由 Antoine Pitrou 在 中提供:issue:`3163`。)


子流程

命令字符串现在可以是 posix 平台上的字节对象。 (由 Victor Stinner 在 中提供:问题:`8513`。)

新常量 DEVNULL 允许以独立于平台的方式抑制输出。 (由 Ross Lagerwall 在 :issue:`5870` 中贡献。)


系统

sys 模块有一个新的 thread_info 名为元组 ,其中包含有关线程实现的信息 (:issue:`11223`)。


tar文件

tarfile 现在通过 lzma 模块支持 [X30X] 编码。 (由 Lars Gustäbel 在 :issue:`5689` 中提供。)


临时文件

tempfile.SpooledTemporaryFile's truncate() 方法现在接受 size 参数。 (由 Ryan Kelly 在 中提供:issue:`9957`。)


文本换行

textwrap 模块有一个新的 indent(),可以直接为文本块中的选定行添加公共前缀 (:issue:`13857` ])。


穿线

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

threading.Thread 构造函数现在接受 daemon 关键字参数来覆盖从父线程继承 daemon 标志值的默认行为 (:issue:` 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.MappingProxyType 类:映射的只读代理。 (:问题:`14386`

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


单元测试

assertRaises()assertRaisesRegex()assertWarns()assertWarnsRegex() 现在接受关键字参数 msg[ X148X] 当用作上下文管理器时。 (由 Ezio Melotti 和 Winston Ewert 在 中提供:issue:`10775`。)

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


网址库

Request 类现在接受 get_method() 使用的 method 参数来确定应该使用什么 HTTP 方法。 例如,这将发送一个 'HEAD' 请求:

>>> urlopen(Request('https://www.python.org', method='HEAD'))

:问题:`1673007`


网页浏览器

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


xml.etree.ElementTree

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


zlib

新属性 zlib.Decompress.eof 可以区分格式正确的压缩流和不完整或截断的流。 (由 Nadeem Vawda 在 中提供:issue:`12646`。)

新属性 zlib.ZLIB_RUNTIME_VERSION 报告在运行时加载的底层 zlib 库的版本字符串。 (由 Torsten Landschoff 在 中提供:issue:`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 提供,:issue:`14624`:issue:`14738`:issue:`15026`。)


已弃用

不支持的操作系统

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

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

在 3.2 中已弃用的 OSF 支持已被完全删除。


弃用的 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

本节列出了可能需要更改您的代码的先前描述的更改和其他错误修正。

移植 Python 代码

  • 默认情况下启用哈希随机化。 将 PYTHONHASHSEED 环境变量设置为 0 以禁用哈希随机化。 另见 object.__hash__() 方法。
  • :issue:`12326`: 在 Linux 上,sys.platform 不再包含主要版本。 它现在总是“linux”,而不是“linux2”或“linux3”,具体取决于用于构建 Python 的 Linux 版本。 将 sys.platform == 'linux2' 替换为 sys.platform.startswith('linux'),如果不需要支持旧的 Python 版本,则直接替换 sys.platform == 'linux'。
  • :issue:`13847`, :issue:`14180`: timedatetime: OverflowError 是如果时间戳超出范围,现在会引发而不是 ValueError。 如果 C 函数 gmtime()localtime() 失败,现在会引发 OSError
  • 导入使用的默认查找器现在使用特定目录中包含的内容的缓存。 如果您创建 Python 源文件或无源字节码文件,请确保调用 importlib.invalidate_caches() 清除缓存,以便查找者注意到新文件。
  • ImportError 现在使用试图导入的模块的全名。 检查 ImportErrors 消息的 Doctests 需要更新以使用模块的全名,而不仅仅是名称的尾部。
  • __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,如果您要清除路径字典中没有查找器的条目,则需要删除与 [ X210X] 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() 函数是标准导入钩子的特例,因此即使它们不提供非标准的 [ X205X] 方法。
  • email.header.decode_header() 完成的解析中长期存在的 RFC 合规性错误 (:issue:`1079`) 已得到修复。 使用标准习语将编码头转换为 unicode (str(make_header(decode_header(h))) 的代码不会有任何变化,但查看 decode_header 返回的单个元组的代码会看到 ASCII 之前或之后的空白部分现在包含在 ASCII 部分中。 使用 make_header 构建头文件的代码也应该继续正常工作,因为 make_header 继续在 ASCII 和非 ASCII 部分之间添加空格,如果是的话尚未出现在输入字符串中。
  • email.utils.formataddr() 现在在传递非 ASCII 显示名称时执行正确的内容传输编码。 任何依赖于先前在格式化输出字符串中保留非 ASCII unicode 的错误行为的代码都需要更改 (:issue:`1690608`)。
  • poplib.POP3.quit() 现在可能会像所有其他 poplib 方法一样引发协议错误。 如果特定应用程序遇到 quit 上的错误,则假定 quit 不会引发 poplib.error_proto 错误的代码可能需要更改(:issue:` 11291`)。
  • email.parser.Parserstrict 参数,自 Python 2.4 起已弃用,最终已被删除。
  • 已弃用的方法 unittest.TestCase.assertSameElements 已被删除。
  • 已弃用的变量 time.accept2dyear 已被删除。
  • 已弃用的 Context._clamp 属性已从 decimal 模块中删除。 它之前被公共属性 clamp 取代。 (参见 :issue:`8540`。)
  • 未公开的内部帮助类 SSLFakeFile 已从 smtplib 中删除,因为它的功能早已由 socket.socket.makefile() 直接提供。
  • 在 Windows 上将负值传递给 time.sleep() 现在会引发错误而不是永远休眠。 它总是在 posix 上引发错误。
  • ast.__version__ 常量已被删除。 如果需要做受AST版本影响的决定,使用sys.version_info来做决定。
  • 用于解决 threading 模块通过子类化私有类使用工厂函数这一事实的代码需要更改为子类化现在的公共类。
  • 删除了线程模块中未记录的调试机制,从而简化了代码。 这应该对生产代码没有影响,但在此处提及以防任何应用程序调试框架与其交互(:issue:`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 字符串)。

    (在 :issue:`14040` 中实现。)


命令行开关更改

  • -Q 命令行标志和相关工件已被删除。 代码检查 sys.flags.division_warning 需要更新。

    :issue:`10998`,由 Éric Araujo 提供。)

  • python-S 开头时,import site 将不再将特定于站点的路径添加到模块搜索路径中。 在以前的版本中,确实如此。

    :issue:`11591`,由 Carl Meyer 提供,由 Éric Araujo 编辑。)