Python 3.3 中的新增功能¶
本文档解释了 Python 3.3 相对于 3.2 的新功能。Python 3.3 于 2012 年 9 月 29 日发布。有关完整详细信息,请参阅更新日志。
参见
PEP 398 - Python 3.3 发布计划
摘要 – 发布亮点¶
新语法功能
新库模块
faulthandler
(有助于调试低级崩溃)ipaddress
(表示 IP 地址和掩码的高级对象)lzma
(使用 XZ / LZMA 算法压缩数据)unittest.mock
(用 mock 对象替换测试系统的一部分)
新的内置功能
重新设计的I/O 异常层次结构。
实现改进
更紧凑的Unicode 字符串。
更紧凑的属性字典。
显著改进的库模块
安全改进
哈希随机化默认启用。
请继续阅读以获取用户可见更改的完整列表。
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+0000
到U+10FFFF
)。窄构建和宽构建之间的区别不再存在,Python 现在表现得像一个宽构建,即使在 Windows 下也是如此。随着窄构建的消亡,窄构建特有的问题也得到了修复,例如
len()
现在始终对非 BMP 字符返回 1,因此len('\U0010FFFF') == 1
;代理对在字符串文字中不再重新组合,因此
'\uDBFF\uDFFF' != '\U0010FFFF'
;索引或切片非 BMP 字符返回预期值,因此
'\U0010FFFF'[0]
现在返回'\U0010FFFF'
而不是'\uDBFF'
;标准库中的所有其他函数现在都能正确处理非 BMP 码点。
sys.maxunicode
的值现在始终为1114111
(十六进制为0x10FFFF
)。PyUnicode_GetMax()
函数为了向后兼容性仍然返回0xFFFF
或0x10FFFF
,并且不应与新的 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 异常层次结构¶
由操作系统错误引发的异常层次结构现在既简化又更细粒度。
您不再需要担心在 OSError
、IOError
、EnvironmentError
、WindowsError
、mmap.error
、socket.error
或 select.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]
推动这一变化的主要原则是,即使是设计用于 send
和 throw
方法的生成器,也可以像将单个大型函数拆分为多个子函数一样容易地拆分为多个子生成器。
参见
- 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.Signature
、inspect.Parameter
和 inspect.BoundArguments
保存有关调用签名(例如,注释、默认值、参数类型和绑定参数)的信息,这大大简化了编写装饰器和任何验证或修改调用签名或参数的代码。
参见
- PEP 362: - 函数签名对象
PEP 由 Brett Cannon、Yury Selivanov、Larry Hastings、Jiwon Seo 撰写;由 Yury Selivanov 实现。
PEP 421:添加 sys.implementation¶
sys
模块上的新属性公开了当前正在运行的解释器实现的特定详细信息。sys.implementation
的初始属性集是 name
、version
、hexversion
和 cache_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.MetaPathFinder
和 importlib.abc.PathEntryFinder
,正确区分了元路径查找器和路径入口查找器。旧的抽象基类 importlib.abc.Finder
现在仅为向后兼容性而提供,不强制任何方法要求。
在查找器方面,importlib.machinery.FileFinder
公开了用于搜索模块源文件和字节码文件的机制。以前,这个类是 sys.path_hooks
的隐式成员。
对于加载器,新的抽象基类 importlib.abc.FileLoader
有助于编写一个使用文件系统作为模块代码存储机制的加载器。源文件加载器(importlib.machinery.SourceFileLoader
)、无源字节码文件加载器(importlib.machinery.SourcelessFileLoader
)和扩展模块加载器(importlib.machinery.ExtensionFileLoader
)现在可以直接使用。
ImportError
现在具有 name
和 path
属性,当有相关数据可提供时会设置这些属性。导入失败的消息现在也将提供模块的完整名称,而不仅仅是模块名称的末尾。
importlib.invalidate_caches()
函数现在将调用 sys.path_importer_cache
中所有缓存的查找器上同名的方法,以根据需要帮助清理任何存储状态。
可见更改¶
有关可能需要的代码更改,请参阅移植 Python 代码一节。
除了 importlib
现在公开的范围之外,导入还有其他可见更改。最大的一点是 sys.meta_path
和 sys.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
bytes
和bytearray
对象的count()
、find()
、rfind()
、index()
和rindex()
方法现在接受 0 到 255 之间的整数作为它们的第一个参数。(由 Petri Lehtinen 在bpo-12170 中贡献。)
bytes
和bytearray
的rjust()
、ljust()
和center()
方法现在接受bytearray
作为fill
参数。(由 Petri Lehtinen 在bpo-12380 中贡献。)list
和bytearray
中添加了新方法: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()
可为 SIGSEGV
、SIGFPE
、SIGABRT
、SIGBUS
和 SIGILL
信号安装故障处理程序。您也可以通过设置 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__
作为动态更新的属性。内置描述符已相应更新。
abc.abstractproperty
已弃用,请改用property
和abc.abstractmethod()
。abc.abstractclassmethod
已弃用,请改用classmethod
和abc.abstractmethod()
。abc.abstractstaticmethod
已弃用,请改用staticmethod
和abc.abstractmethod()
。
(由 Darren Dale 在bpo-11610 中贡献。)
abc.ABCMeta.register()
现在返回注册的子类,这意味着它现在可以用作类装饰器(bpo-10868)。
array¶
array
模块支持使用 q
和 Q
类型代码的 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.BZ2File
和bz2.decompress()
现在可以解压缩多流输入(例如 pbzip2 工具产生的输入)。bz2.BZ2File
现在也可以使用'a'
(追加)模式创建此类文件。(由 Nir Aides 在bpo-1625 中贡献。)
bz2.BZ2File
现在实现了io.BufferedIOBase
API 的所有功能,除了detach()
和truncate()
方法。
codecs¶
mbcs
编码器已重写,以在所有 Windows 版本上正确处理 replace
和 ignore
错误处理程序。mbcs
编码器现在支持所有错误处理程序,而不是仅支持 replace
进行编码和 ignore
进行解码。
添加了一个新的仅限 Windows 的编码器:cp65001
(bpo-13216)。它是 Windows 代码页 65001 (Windows UTF-8, CP_UTF8
)。例如,如果控制台输出代码页设置为 cp65001(例如,使用 chcp 65001
命令),则由 sys.stdout
使用。
多字节 CJK 解码器现在重新同步更快。它们只忽略无效字节序列的第一个字节。例如,b'\xff\n'.decode('gb2312', 'replace')
现在在替换字符后返回一个 \n
。
增量 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.'
。
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
模块中的同步对象)中获取资源,都能正常工作。
crypt¶
crypt
模块中增加了 salt 和模块化加密格式(哈希方法)以及 mksalt()
函数。
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¶
朴素和感知
datetime
实例之间的相等比较现在返回False
,而不是引发TypeError
(bpo-15006)。新的
datetime.datetime.timestamp()
方法:返回对应于datetime
实例的 POSIX 时间戳。datetime.datetime.strftime()
方法支持格式化早于 1000 年的年份。datetime.datetime.astimezone()
方法现在可以不带参数调用,以将 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 模块具有以下上下文限制,具体取决于机器架构
在上下文模板(
DefaultContext
、BasicContext
和ExtendedContext
)中,Emax
和Emin
的量级已更改为999999
。decimal.py 中的
Decimal
构造函数不遵守上下文限制,并精确转换具有任意指数或精度的值。由于 C 版本具有内部限制,因此使用了以下方案:如果可能,精确转换值,否则引发InvalidOperation
且结果为 NaN。在后一种情况下,始终可以使用create_decimal()
来获取舍入或不精确的值。decimal.py 中的幂函数始终正确舍入。在 C 版本中,它由正确舍入的
exp()
和ln()
函数定义,但最终结果仅是“几乎总是正确舍入”。在 C 版本中,包含信号的上下文字典是
MutableMapping
。出于速度原因,flags
和traps
始终指向上下文初始化时使用的同一个MutableMapping
。如果分配了新的信号字典,flags
和traps
将使用新值进行更新,但它们不引用 RHS 字典。腌制
Context
会产生不同的输出,以实现 Python 和 C 版本的通用交换格式。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 |
当 |
linesep |
当 |
cte_type |
|
raise_on_defect |
导致 |
一个新的策略实例,具有新的设置,是通过策略对象的 clone()
方法创建的。clone
将上述任何控件作为关键字参数。任何未在调用中指定的控件都保留其默认值。因此,您可以创建使用 \r\n
换行符的策略,如下所示
mypolicy = compat32.clone(linesep='\r\n')
策略可以使您的应用程序生成所需格式的消息变得更简单。您无需记住在所有调用 generator
的地方都指定 linesep='\r\n'
,您可以在设置 parser
或 Message
使用的策略时指定一次,无论您的程序使用哪个来创建 Message
对象。另一方面,如果您需要生成多种形式的消息,您仍然可以在相应的 generator
调用中指定参数。或者您可以为不同的情况使用自定义策略实例,并在创建 generator
时传递这些实例。
带有新 Header API 的临时策略¶
尽管策略框架本身就很有价值,但引入它的主要动机是允许创建新策略,以一种为不使用新策略的人保持向后兼容性的方式实现 email 包的新功能。由于新策略引入了新的 API,我们将在 Python 3.3 中将其作为临时策略发布。如果核心开发人员认为有必要,可能会发生向后不兼容的更改(包括代码的删除)。
新策略是 EmailPolicy
的实例,并添加了以下附加控制
refold_source |
控制由 |
header_factory |
一个可调用对象,它接受一个 |
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>'
解析消息时,您可以使用头部对象的 addresses
和 groups
属性来访问组和单个地址
>>> 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。
新的实用函数
format_datetime()
:给定一个datetime
,生成一个格式化用于电子邮件头部的字符串。parsedate_to_datetime()
:给定一个来自电子邮件头部的日期字符串,将其转换为感知型datetime
,如果偏移量为-0000
,则转换为非感知型datetime
。localtime()
:不带参数时,返回当前本地时间作为使用本地timezone
的感知型datetime
。给定一个感知型datetime
,将其转换为使用本地timezone
的感知型datetime
。
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-14538、bpo-13993、bpo-13960、bpo-13358、bpo-1745761、bpo-755670、bpo-13357、bpo-12629、bpo-1200313、bpo-670664、bpo-13273、bpo-12888、bpo-7311 中贡献。)
一个新的 html5
字典已添加到 html.entities
模块中,它将 HTML5 命名字符引用映射到等效的 Unicode 字符(例如 html5['gt;'] == '>'
)。现在 HTMLParser
也使用该字典。(由 Ezio Melotti 在 bpo-11113 和 bpo-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_through 为 True
,则对 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¶
os
模块有一个新的pipe2()
函数,它使得可以原子地创建带有O_CLOEXEC
或O_NONBLOCK
标志的管道。这对于避免多线程程序中的竞争条件特别有用。os
模块有一个新的sendfile()
函数,它提供了一种高效的“零拷贝”方式来将数据从一个文件(或套接字)描述符复制到另一个。短语“零拷贝”指的是两个描述符之间所有数据复制完全由内核完成,没有数据复制到用户空间缓冲区。sendfile()
可用于高效地将数据从磁盘上的文件复制到网络套接字,例如下载文件。(补丁由 Ross Lagerwall 和 Giampaolo Rodolà 在 bpo-10882 中提交。)
为了避免诸如符号链接攻击以及临时文件和目录问题等竞争条件,操作文件描述符而不是文件名更可靠(也更快)。Python 3.3 增强了现有函数并引入了新函数来处理文件描述符(bpo-4761、bpo-10755 和 bpo-14626)。
os
模块有一个新的fwalk()
函数,类似于walk()
,但它也产生引用所访问目录的文件描述符。这对于避免符号链接竞争特别有用。以下函数获取新的可选 dir_fd (相对于目录描述符的路径)和/或 follow_symlinks (不跟踪符号链接):
access()
、chflags()
、chmod()
、chown()
、link()
、lstat()
、mkdir()
、mkfifo()
、mknod()
、open()
、readlink()
、remove()
、rename()
、replace()
、rmdir()
、stat()
、symlink()
、unlink()
、utime()
。对这些参数的平台支持可以通过集合os.supports_dir_fd
和os.supports_follow_symlinks
进行检查。以下函数现在支持将其路径参数作为文件描述符:
chdir()
、chmod()
、chown()
、execve()
、listdir()
、pathconf()
、exists()
、stat()
、statvfs()
、utime()
。对这些参数的平台支持可以通过os.supports_fd
集进行检查。
access()
接受一个effective_ids
关键字参数,以在访问检查中启用使用有效 uid/gid 而不是实际 uid/gid。平台对此的支持可以通过supports_effective_ids
集进行检查。os
模块有两个新函数:getpriority()
和setpriority()
。它们可用于获取或设置进程的优先级/优先权,其方式类似于os.nice()
,但扩展到所有进程而不仅仅是当前进程。(补丁由 Giampaolo Rodolà 在 bpo-10784 中提交。)
新的
os.replace()
函数允许跨平台重命名文件并覆盖目标文件。使用os.rename()
,在 POSIX 下会覆盖现有目标文件,但在 Windows 下会引发错误。(由 Antoine Pitrou 在 bpo-8828 中贡献。)stat 系列函数(
stat()
、fstat()
和lstat()
)现在支持以纳秒精度读取文件的时间戳。对称地,utime()
现在可以以纳秒精度写入文件时间戳。(由 Larry Hastings 在 bpo-14127 中贡献。)新的
os.get_terminal_size()
函数查询连接到文件描述符的终端大小。另请参阅shutil.get_terminal_size()
。(由 Zbigniew Jędrzejewski-Szmek 在 bpo-13609 中贡献。)
支持 Linux 扩展属性的新函数(bpo-12720):
getxattr()
、listxattr()
、removexattr()
、setxattr()
。调度器的新接口。这些函数控制操作系统如何为进程分配 CPU 时间。新函数:
sched_get_priority_max()
、sched_get_priority_min()
、sched_getaffinity()
、sched_getparam()
、sched_getscheduler()
、sched_rr_get_interval()
、sched_setaffinity()
、sched_setparam()
、sched_setscheduler()
、sched_yield()
。控制文件系统的新函数
posix_fadvise()
:声明以特定模式访问数据的意图,从而允许内核进行优化。posix_fallocate()
:确保为文件分配足够的磁盘空间。sync()
:强制将所有内容写入磁盘。
其他新的 posix 函数
lockf()
:对打开的文件描述符应用、测试或移除 POSIX 锁。pread()
:从文件描述符的某个偏移量处读取,文件偏移量保持不变。pwrite()
:从文件描述符的某个偏移量处写入,文件偏移量保持不变。readv()
:从文件描述符读取到多个可写缓冲区中。truncate()
:截断与 path 对应的文件,使其大小最多为 length 字节。waitid()
:等待一个或多个子进程完成。writev()
:将 buffers 的内容写入文件描述符,其中 buffers 是任意缓冲区序列。getgrouplist()
(bpo-9344):返回指定用户所属的组 ID 列表。
一些平台现在支持
lseek()
函数的附加常量,例如os.SEEK_HOLE
和os.SEEK_DATA
。新的常量
RTLD_LAZY
、RTLD_NOW
、RTLD_GLOBAL
、RTLD_LOCAL
、RTLD_NODELETE
、RTLD_NOLOAD
和RTLD_DEEPBIND
在支持它们的平台上可用。它们用于sys.setdlopenflags()
函数,并取代ctypes
和DLFCN
中定义的类似常量。(由 Victor Stinner 在 bpo-13226 中贡献。)os.symlink()
现在在非 Windows 平台上接受(并忽略)target_is_directory
关键字参数,以简化跨平台支持。
pdb¶
现在,Tab 补全不仅适用于命令名称,也适用于其参数。例如,对于 break
命令,函数和文件名都可以补全。
(由 Georg Brandl 在 bpo-14210 中贡献)
pickle¶
pickle.Pickler
对象现在有一个可选的 dispatch_table
属性,允许设置每个 pickler 的缩减函数。
(由 Richard Oudkerk 在 bpo-14166 中贡献。)
pydoc¶
Tk GUI 和 serve()
函数已从 pydoc
模块中移除:pydoc -g
和 serve()
已在 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
类构造函数的 timefunc 和 delayfunct 参数现在是可选的,分别默认为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-14127 和 bpo-15238 中贡献。)现在有几个函数接受可选的
symlinks
参数:当该参数为 True 时,符号链接不会被解除引用,而是对符号链接本身执行操作(如果相关,则创建一个)。(由 Hynek Schlawack 在 bpo-12715 中贡献。)将文件复制到不同的文件系统时,
move()
现在像 posixmv
命令那样处理符号链接,重新创建符号链接而不是复制目标文件内容。(由 Jonathan Niehof 在 bpo-9993 中贡献。)move()
现在也将其结果返回为dst
参数。rmtree()
现在对支持os.open()
和os.unlink()
中新dir_fd
参数的平台上的符号链接攻击具有抵抗力。(由 Martin von Löwis 和 Hynek Schlawack 在 bpo-4489 中贡献。)
信号¶
signal
模块有新函数pthread_sigmask()
:获取和/或更改调用线程的信号掩码(由 Jean-Paul Calderone 在 bpo-8407 中贡献);pthread_kill()
:向线程发送信号;sigpending()
:检查待处理的函数;sigwait()
:等待信号;sigwaitinfo()
:等待信号,返回有关该信号的详细信息;sigtimedwait()
:与sigwaitinfo()
类似,但带有超时。
信号处理程序将信号编号作为一个字节而不是空字节写入唤醒文件描述符。因此,可以等待多个信号并知道哪些信号被触发。
signal.signal()
和signal.siginterrupt()
引发 OSError,而不是 RuntimeError:OSError 具有 errno 属性。
smtpd¶
smtpd
模块现在支持 RFC 5321(扩展 SMTP)和 RFC 1870(大小扩展)。根据标准,这些扩展仅在客户端使用 EHLO
命令启动会话时才启用。
(初始 ELHO
支持由 Alberto Trevino 贡献。大小扩展由 Juhana Jauhiainen 贡献。补丁的实质性额外工作由 Michele Orrù 和 Dan Boswell 贡献。 bpo-8739)
smtplib¶
SMTP
、SMTP_SSL
和 LMTP
类现在接受 source_address
关键字参数,用于在创建出站套接字时在绑定调用中指定用作源地址的 (host, port)
。(由 Paulo Scardine 在 bpo-11281 中贡献。)
SMTP
现在支持上下文管理协议,允许在 with
语句中使用 SMTP
实例。(由 Giampaolo Rodolà 在 bpo-11289 中贡献。)
SMTP_SSL
构造函数和 starttls()
方法现在接受 SSLContext 参数来控制安全通道的参数。(由 Kasun Herath 在 bpo-8809 中贡献。)
socket¶
socket
类现在公开了额外的辅助数据处理方法,前提是底层平台支持它们(由 David Watson 在 bpo-6560 中贡献,基于 Heiko Wundram 之前的补丁)
socket
类现在在 Linux 上支持 PF_CAN 协议族(https://en.wikipedia.org/wiki/Socketcan)。(由 Matthias Fuchs 贡献,Tiago Gonçalves 在 bpo-10141 中更新。)
socket
类现在支持 PF_RDS 协议族(https://en.wikipedia.org/wiki/Reliable_Datagram_Sockets 和 https://oss.oracle.com/projects/rds)。socket
类现在在 OS X 上支持PF_SYSTEM
协议族。(由 Michael Goderbauer 在 bpo-13777 中贡献。)新函数
sethostname()
允许在 Unix 系统上设置主机名,如果调用进程具有足够的权限。(由 Ross Lagerwall 在 bpo-10866 中贡献。)
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-13626 和 bpo-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 中贡献。)由于
library
和reason
属性,现在可以更轻松地检查 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
模块现在通过新代码 n
和 N
分别支持 ssize_t
和 size_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.SpooledTemporaryFile
的 truncate()
方法现在接受 size
参数。(由 Ryan Kelly 在 bpo-9957 中贡献。)
textwrap¶
textwrap
模块有一个新的 indent()
函数,可以方便地为文本块中选定的行添加通用前缀(bpo-13857)。
threading¶
threading.Condition
、threading.Semaphore
、threading.BoundedSemaphore
、threading.Event
和 threading.Timer
,所有这些曾经是返回类实例的工厂函数,现在都是类并且可以被子类化。(由 Éric Araujo 在 bpo-10968 中贡献。)
threading.Thread
构造函数现在接受 daemon
关键字参数,以覆盖从父线程继承 daemon
标志值的默认行为(bpo-6064)。
以前的私有函数 _thread.get_ident
现在作为公共函数 threading.get_ident()
可用。这消除了 stdlib 中对 _thread
模块的几个直接访问情况。使用 _thread.get_ident
的第三方代码也应更改为使用新的公共接口。
时间¶
get_clock_info()
:获取时钟信息。monotonic()
:单调时钟(不能倒退),不受系统时钟更新影响。perf_counter()
:具有最高可用分辨率的性能计数器,用于测量短持续时间。process_time()
:当前进程的系统和用户 CPU 时间的总和。
其他新函数
clock_getres()
、clock_gettime()
和clock_settime()
函数与CLOCK_xxx
常量。(由 Victor Stinner 在 bpo-10278 中贡献。)
为了提高跨平台的一致性,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'))
webbrowser¶
webbrowser
模块支持更多“浏览器”:Google Chrome(根据版本和操作系统命名为 chrome、chromium、chrome-browser 或 chromium-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
(此模块出于向后兼容性而保留,但现在已弃用)。此外,Element
的 iter
系列方法已得到优化(用 C 重写)。该模块的文档也得到了极大改进,增加了示例和更详细的参考。
zlib¶
新属性 zlib.Decompress.eof
使区分格式正确的压缩流和不完整或截断的压缩流成为可能。(由 Nadeem Vawda 在 bpo-12646 中贡献。)
新属性 zlib.ZLIB_RUNTIME_VERSION
报告运行时加载的底层 zlib
库的版本字符串。(由 Torsten Landschoff 在 bpo-12306 中贡献。)
优化¶
已添加主要的性能增强
构建和 C API 更改¶
Python 的构建过程和 C API 的更改包括
新的 PEP 3118 相关函数
PEP 393 添加了新的 Unicode 类型、宏和函数
高级 API
低级 API
PyUnicode_DATA
,PyUnicode_1BYTE_DATA
,PyUnicode_2BYTE_DATA
,PyUnicode_4BYTE_DATA
PyUnicode_KIND
与PyUnicode_Kind
枚举:PyUnicode_WCHAR_KIND
、PyUnicode_1BYTE_KIND
、PyUnicode_2BYTE_KIND
、PyUnicode_4BYTE_KIND
PyArg_ParseTuple
现在接受bytearray
作为c
格式(bpo-12380)。
已弃用¶
不支持的操作系统¶
由于缺乏维护者,不再支持 OS/2 和 VMS。
由于维护负担,不再支持 Windows 2000 和将 COMSPEC
设置为 command.com
的 Windows 平台。
OSF 支持已在 3.2 中弃用,现已完全删除。
已弃用的 Python 模块、函数和方法¶
向
object.__format__()
传递非空字符串已被弃用,并将在 Python 3.4 中产生TypeError
(bpo-9856)。unicode_internal
编解码器已弃用,因为 PEP 393,请使用 UTF-8、UTF-16(utf-16-le
或utf-16-be
)或 UTF-32(utf-32-le
或utf-32-be
)platform.popen()
:使用subprocess
模块。特别检查 使用子进程模块替换旧函数 部分(bpo-11377)。bpo-13374:
os
模块中的 Windows 字节 API 已弃用。使用 Unicode 文件名而不是字节文件名,以便不再依赖 ANSI 代码页并支持任何文件名。bpo-13988:
xml.etree.cElementTree
模块已弃用。加速器在可用时会自动使用。time.clock()
的行为取决于平台:根据您的要求,使用新的time.perf_counter()
或time.process_time()
函数,以获得明确定义的行为。os.stat_float_times()
函数已弃用。abc
模块abc.abstractproperty
已弃用,请改用property
和abc.abstractmethod()
。abc.abstractclassmethod
已弃用,请改用classmethod
和abc.abstractmethod()
。abc.abstractstaticmethod
已弃用,请改用staticmethod
和abc.abstractmethod()
。
-
importlib.abc.SourceLoader.path_mtime()
现已弃用,转而使用importlib.abc.SourceLoader.path_stats()
,因为字节码文件现在存储字节码文件编译自的源文件的修改时间和大小。
已弃用的 C API 函数和类型¶
Py_UNICODE
已被 PEP 393 弃用,并将在 Python 4 中删除。所有使用此类型的函数均已弃用
使用 Py_UNICODE
和 Py_UNICODE* 类型的 Unicode 函数和方法
PyUnicode_FromUnicode
:使用PyUnicode_FromWideChar()
或PyUnicode_FromKindAndData()
PyUnicode_AS_UNICODE
、PyUnicode_AsUnicode()
、PyUnicode_AsUnicodeAndSize()
:使用PyUnicode_AsWideCharString()
PyUnicode_AS_DATA
:使用PyUnicode_DATA
和PyUnicode_READ
和PyUnicode_WRITE
PyUnicode_GET_SIZE
、PyUnicode_GetSize()
:使用PyUnicode_GET_LENGTH
或PyUnicode_GetLength()
PyUnicode_GET_DATA_SIZE
:使用PyUnicode_GET_LENGTH(str) * PyUnicode_KIND(str)
(仅适用于已准备好的字符串)PyUnicode_AsUnicodeCopy()
:使用PyUnicode_AsUCS4Copy()
或PyUnicode_AsWideCharString()
PyUnicode_GetMax()
操纵 Py_UNICODE* 字符串的函数和宏
Py_UNICODE_strlen()
:使用PyUnicode_GetLength()
或PyUnicode_GET_LENGTH
Py_UNICODE_strcat()
:使用PyUnicode_CopyCharacters()
或PyUnicode_FromFormat()
Py_UNICODE_strcpy()
、Py_UNICODE_strncpy()
、Py_UNICODE_COPY()
:使用PyUnicode_CopyCharacters()
或PyUnicode_Substring()
Py_UNICODE_strcmp()
:使用PyUnicode_Compare()
Py_UNICODE_strncmp()
:使用PyUnicode_Tailmatch()
Py_UNICODE_strchr()
、Py_UNICODE_strrchr()
:使用PyUnicode_FindChar()
Py_UNICODE_FILL()
:使用PyUnicode_Fill()
Py_UNICODE_MATCH
编码器
PyUnicode_Encode()
:使用PyUnicode_AsEncodedObject()
PyUnicode_EncodeUTF7()
PyUnicode_EncodeUTF8()
:使用PyUnicode_AsUTF8()
或PyUnicode_AsUTF8String()
PyUnicode_EncodeUTF32()
PyUnicode_EncodeUTF16()
PyUnicode_EncodeUnicodeEscape()
使用PyUnicode_AsUnicodeEscapeString()
PyUnicode_EncodeRawUnicodeEscape()
使用PyUnicode_AsRawUnicodeEscapeString()
PyUnicode_EncodeLatin1()
:使用PyUnicode_AsLatin1String()
PyUnicode_EncodeASCII()
:使用PyUnicode_AsASCIIString()
PyUnicode_EncodeCharmap()
PyUnicode_TranslateCharmap()
PyUnicode_EncodeMBCS()
:使用PyUnicode_AsMBCSString()
或PyUnicode_EncodeCodePage()
(带CP_ACP
代码页)PyUnicode_EncodeDecimal()
、PyUnicode_TransformDecimalToASCII()
已弃用的功能¶
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-13847,bpo-14180:
time
和datetime
:如果时间戳超出范围,现在会引发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_path
和sys.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.Parser
的strict
参数最终已被删除。已弃用的方法
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.h
或object.h
中相关部分的扩展都必须重建。由于 PEP 393,
Py_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.so
、xxxmodule.abi3.so
和xxxmodule.cpython-*.so
的文件不再被识别为实现xxx
模块。如果您一直在生成此类文件,则必须切换到其他拼写(即,从文件名中删除module
字符串)。(在 bpo-14040 中实现。)