Python 3.3 的新特性 — Python 文档
Python 3.3 中的新功能
本文解释了 Python 3.3 中与 3.2 相比的新特性。 Python 3.3 于 2012 年 9 月 29 日发布。 有关完整详细信息,请参阅 变更日志 。
摘要 – 发布亮点
新的语法特性:
- 用于 生成器委托 的新
yield from
表达式。 - [[Python/docs/3.9/library/stdtypes#str|]] 对象再次接受
u'unicode'
语法。
新的库模块:
- faulthandler(帮助调试低级崩溃)
- ipaddress(代表IP地址和掩码的高级对象)
- lzma(使用XZ/LZMA算法压缩数据)
- unittest.mock(用模拟对象替换被测系统的部分)
- venv(Python 虚拟环境,如流行的
virtualenv
包)
新的内置功能:
- 重做 I/O 异常层次结构 。
实施改进:
- 基于 importlib 重写了 import Machinery。
- 更紧凑的 unicode 字符串 。
- 更紧凑的 属性字典 。
显着改进的库模块:
- decimal 模块的 C 加速器。
- email 模块中更好的 unicode 处理(provisional)。
安全改进:
- 默认情况下启用哈希随机化。
请继续阅读以获取面向用户的更改的完整列表。
PEP 405:虚拟环境
虚拟环境有助于创建单独的 Python 设置,同时共享系统范围的基本安装,以便于维护。 虚拟环境有自己的一组私有站点包(即 本地安装的库),并且可以选择与系统范围的站点包隔离。 它们的概念和实现受到流行的 virtualenv
第三方软件包的启发,但受益于与解释器核心的更紧密集成。
此 PEP 添加了用于编程访问的 venv 模块,以及用于命令行访问和管理的 pyvenv
脚本。 Python 解释器检查 pyvenv.cfg
文件,该文件的存在标志着虚拟环境目录树的基础。
PEP 420:隐式命名空间包
对不需要 __init__.py
标记文件并且可以自动跨越多个路径段的包目录的本机支持(受各种第三方命名空间包方法的启发,如 PEP 420 中所述)
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 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
)。 窄构建和宽构建之间的区别不再存在,即使在 Windows 下,Python 现在也表现得像宽构建。 - 随着窄构建的消亡,窄构建特有的问题也得到了修复,例如:
- len() 现在总是为非 BMP 字符返回 1,所以
len('\U0010FFFF') == 1
; - 代理对不会在字符串文字中重新组合,因此
'\uDBFF\uDFFF' != '\U0010FFFF'
; - 索引或切片非 BMP 字符返回预期值,因此
'\U0010FFFF'[0]
现在返回'\U0010FFFF'
而不是'\uDBFF'
; - 标准库中的所有其他函数现在可以正确处理非 BMP 代码点。
- len() 现在总是为非 BMP 字符返回 1,所以
- sys.maxunicode 的值现在总是
1114111
(十六进制的0x10FFFF
)。PyUnicode_GetMax()
函数仍返回0xFFFF
或0x10FFFF
以实现向后兼容性,并且不应与新的 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 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 异常层次结构
操作系统错误引发的异常层次结构现在既简化又细化。
您不必再担心在 OSError、IOError、EnvironmentError、WindowsError、mmap.error
、socket.error 或 select.error。 所有这些异常类型现在只有一种:OSError。 出于兼容性原因,其他名称保留为别名。
此外,现在更容易捕获特定的错误情况。 无需检查来自 errno 模块的特定常量的 errno
属性(或 args[0]
),您可以捕获足够的 OSError 子类。 可用的子类如下:
BlockingIOError
ChildProcessError
ConnectionError
FileExistsError
FileNotFoundError
InterruptedError
IsADirectoryError
NotADirectoryError
PermissionError
ProcessLookupError
TimeoutError
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 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 414:显式 Unicode 文字
为了简化从 Python 2 过渡到大量使用 Unicode 文字的 Unicode 感知 Python 应用程序,Python 3.3 再次支持字符串文字的“u
”前缀。 这个前缀在 Python 3 中没有语义意义,提供它只是为了减少迁移到 Python 3 的纯机械变化的数量,使开发人员更容易关注更重要的语义变化(例如更严格的二进制默认分离和文本数据)。
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 412:密钥共享字典
用于存储对象属性的字典现在能够在彼此之间共享其内部存储的一部分(即,存储键及其各自哈希的部分)。 这减少了创建许多非内置类型实例的程序的内存消耗。
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
来控制模块的缓存行为。
简单命名空间
sys.implementation
的实现还为 Python 引入了一个新类型:types.SimpleNamespace。 与基于映射的命名空间(如 dict)相比,SimpleNamespace
是基于属性的,如 object。 但是,与 object
不同,SimpleNamespace
实例是可写的。 这意味着您可以通过正常的属性访问来添加、删除和修改命名空间。
使用 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 现在具有 name
和 path
属性,当需要提供相关数据时会设置这些属性。 导入失败的消息现在还将提供模块的全名,而不仅仅是模块名称的尾端。
importlib.invalidate_caches() 函数现在将在缓存在 sys.path_importer_cache 中的所有查找器上调用具有相同名称的方法,以帮助根据需要清理任何存储的状态。
可见的变化
如需对代码进行潜在的必要更改,请参阅 移植 Python 代码 部分。
除了 importlib 现在公开的内容之外,还有其他可见的更改要导入。 最大的是 sys.meta_path 和 sys.path_hooks 现在存储导入使用的所有元路径查找器和路径条目挂钩。 以前,查找器是隐式的,隐藏在导入的 C 代码中,而不是直接公开。 这意味着现在可以轻松删除或更改各种查找器的顺序以满足自己的需要。
另一个变化是所有模块都有一个 __loader__
属性,存储用于创建模块的加载器。 PEP 302 已经更新,强制加载器实现这个属性,所以将来一旦 3rd-party loader 更新,人们将能够依赖属性。 不过,在此之前,import 会在加载后设置模块。
现在,加载器还需要设置 PEP 366 中的 __package__
属性。 再一次, import 本身已经在所有来自 importlib 的加载器上设置了这个,并且 import 本身正在设置 post-load 属性。
None
现在插入 sys.path_importer_cache 当 sys.path_hooks 上没有发现者时。 由于 imp.NullImporter 没有直接暴露在 sys.path_hooks 上,因此不能再依赖它始终可用作表示未找到发现者的值。
所有其他更改都与更新 Python 3.3 代码时应考虑的语义更改有关,因此应在本文档的 移植 Python 代码 部分阅读。
(由 Brett Cannon 实施)
其他语言更改
对核心 Python 语言进行的一些较小更改是:
添加了对 Unicode 名称别名和命名序列的支持。 unicodedata.lookup() 和
'\N{...}'
现在都解析名称别名,unicodedata.lookup() 也解析命名序列。(由 Ezio Melotti 在 中提供:issue:`12753`。)
Unicode 数据库更新至 UCD 版本 6.1.0
range() 对象上的相等性比较现在返回一个结果,反映由这些范围对象生成的底层序列的相等性。 (:问题:`13201`)
count()
,find()
,rfind()
,index()
和rindex()
方法 bytes 和 bytearray[ X104X] 对象现在接受 0 到 255 之间的整数作为它们的第一个参数。(由 Petri Lehtinen 在 中提供:issue:`12170`。)
rjust()
、ljust()
和center()
方法 bytes 和 bytearray 现在接受 bytearrayfill
参数。 (由 Petri Lehtinen 在 中提供:issue:`12380`。)新方法已添加到 list 和 bytearray:
copy()
和clear()
(:issue:`10516`)。 因此,MutableSequence 现在还定义了一个clear()
方法 (:issue:`11388`)。原始字节文字现在可以写为
rb"..."
以及br"..."
。(由 Antoine Pitrou 在 中提供:issue:`13748`。)
dict.setdefault() 现在只对给定的键进行一次查找,使其在与内置类型一起使用时具有原子性。
(由 Filip Gruszczyński 在 :issue:`13521` 中提供。)
函数调用与函数签名不匹配时产生的错误消息已得到显着改善。
(本杰明·彼得森供稿。)
更细粒度的导入锁
以前版本的 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() 为 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
IP地址
新的 ipaddress 模块提供了用于创建和操作代表 IPv4 和 IPv6 地址、网络和接口的对象的工具(即 与特定 IP 子网关联的 IP 地址)。
(由 Google 和 Peter Moody 在 PEP 3144 中提供。)
lzma
新增的 lzma 模块提供了使用 LZMA 算法的数据压缩和解压,包括对 .xz
和 .lzma
文件格式的支持。
(由 Nadeem Vawda 和 Per Øyvind Karlsen 在 中提供:issue:`6715`。)
改进的模块
美国广播公司
改进了对包含用抽象方法组成的描述符的抽象基类的支持。 现在推荐的声明抽象描述符的方法是提供 __isabstractmethod__
作为动态更新的属性。 内置描述符已相应更新。
- abc.abstractproperty 已被弃用,使用 property 和 abc.abstractmethod() 代替。
- abc.abstractclassmethod 已被弃用,使用 classmethod 和 abc.abstractmethod() 代替。
- abc.abstractstaticmethod 已被弃用,使用 staticmethod 和 abc.abstractmethod() 代替。
(由 Darren Dale 在 中提供:问题:`11610`。)
abc.ABCMeta.register() 现在返回注册的子类,这意味着它现在可以用作类装饰器 (:issue:`10868`)。
大批
array 模块支持使用 q
和 Q
类型代码的 long long 类型。
(由 Oren Tirosh 和 Hirokazu Yamamoto 在 中提供:issue:`1172711`。)
base64
base64 现代接口的解码功能现在接受仅 ASCII 的 Unicode 字符串。 例如,base64.b64decode('YWJj')
返回 b'abc'
。 (由 Catalin Iacob 在 :issue:`13641` 中提供。)
bz2
bz2 模块已从头开始重写。 在此过程中,添加了几个新功能:
新的 bz2.open() 函数:以二进制或文本模式打开 bzip2 压缩文件。
bz2.BZ2File 现在可以通过其构造函数的 fileobj 参数读取和写入任意类文件对象。
(由 Nadeem Vawda 在 中提供:issue:`5863`。)
bz2.BZ2File 和 bz2.decompress() 现在可以解压缩多流输入(例如由 pbzip2 工具生成的那些)。 bz2.BZ2File 现在也可用于创建此类文件,使用
'a'
(附加)模式。(由 Nir Aides 在 中提供:issue:`1625`。)
bz2.BZ2File 现在实现了所有的 io.BufferedIOBase API,除了
detach()
和truncate()
方法。
编解码器
mbcs 编解码器已被重写,以正确处理所有 Windows 版本上的 replace
和 ignore
错误处理程序。 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
。
增量 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
编解码器已被弃用。
收藏
添加新的 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 模块的同步对象)。
诅咒
- 如果 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` 中贡献。)
约会时间
- naive 和aware datetime 实例之间的相等比较现在返回 False 而不是引发 TypeError (:issue:`15006`)。
- 新的 datetime.datetime.timestamp() 方法:返回对应于 datetime 实例的 POSIX 时间戳。
- datetime.datetime.strftime() 方法支持格式化早于 1000 年的年份。
- datetime.datetime.astimezone() 方法现在可以在不带参数的情况下调用,以将日期时间实例转换为系统时区。
十进制
- :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
在上下文模板(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
参数已弃用。
电子邮件
政策框架
电子邮件包现在有一个 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 7bit
或8bit
。8bit
仅适用于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 的实例,并添加以下附加控件:
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 字符串,并且电子邮件包透明地对 unicode 与 RFC 标准内容传输编码进行编码和解码。
其他 API 更改
新增 BytesHeaderParser,添加到 parser 模块以补充 HeaderParser 并完善 Bytes API。
新的实用功能:
- format_datetime():给定一个 datetime,生成一个格式化的字符串以用于电子邮件标题。
- parsedate_to_datetime():给定来自电子邮件标题的日期字符串,将其转换为可感知的 datetime,如果偏移量为 [ X170X]。
- localtime():不带参数,使用本地 timezone 返回当前本地时间作为感知 datetime。 给定一个有意识的 datetime,使用本地 timezone 将其转换为一个有意识的 datetime。
ftplib
- ftplib.FTP 现在接受
source_address
关键字参数来指定(host, port)
在创建传出套接字时用作绑定调用中的源地址。 (由 Giampaolo Rodolà 在 :issue:`8594` 中提供。) - FTP_TLS 类现在提供了一个新的 ccc() 函数来将控制通道恢复为明文。 这对于利用知道如何通过非安全 FTP 处理 NAT 而不打开固定端口的防火墙很有用。 (由 Giampaolo Rodolà 在 中提供:issue:`12139`。)
- 添加了 ftplib.FTP.mlsd() 方法,该方法提供可解析的目录列表格式并弃用 ftplib.FTP.nlst() 和 ftplib.FTP.dir() ]。 (由 Giampaolo Rodolà 在 中提供:issue:`11072`。)
功能工具
functools.lru_cache() 装饰器现在接受 typed
关键字参数(默认为 False
以确保它缓存不同类型的值,这些值在不同的缓存槽中比较相等. (由 Raymond Hettinger 在 中提供:issue:`13227`。)
海马
添加了新的 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` 中贡献。)
检查
添加了一个新的 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_through 是 True
,则保证不会缓冲对 write()
的调用:写入 TextIOWrapper 对象的任何数据都会立即处理到其底层二进制缓冲区。
日志记录
basicConfig() 函数现在支持可选的 handlers
参数,该参数将可迭代的处理程序添加到根记录器中。
类级别属性 append_nul
已添加到 SysLogHandler 以允许控制将 NUL
(\000
) 字节附加到系统日志记录,因为对于有些守护进程需要它,而对于其他守护进程,它被传递到日志中。
映射
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` 中提供。)
操作系统
os 模块有一个新的 pipe2() 函数,可以创建一个带有 O_CLOEXEC 或 O_NONBLOCK 标志的管道。 这对于避免多线程程序中的竞争条件特别有用。
os 模块有一个新的 sendfile() 函数,它提供了一种有效的“零复制”方式来将数据从一个文件(或套接字)描述符复制到另一个文件(或套接字)描述符。 短语“零复制”是指两个描述符之间的所有数据复制完全由内核完成,没有将数据复制到用户空间缓冲区中。 sendfile() 可用于有效地将数据从磁盘上的文件复制到网络套接字,例如 用于下载文件。
(由 Ross Lagerwall 和 Giampaolo Rodolà 在 中提交的补丁:问题:`10882`。)
为了避免符号链接攻击和临时文件和目录问题等竞争条件,操作文件描述符而不是文件名更可靠(也更快)。 Python 3.3 增强了现有函数并引入了处理文件描述符的新函数(:issue:`4761`, :issue:`10755` 和 :issue:`14626` )。
os 模块有一个新的 fwalk() 函数,类似于 walk() ,除了它还产生引用所访问目录的文件描述符。 这对于避免符号链接竞争特别有用。
以下函数获得新的可选 dir_fd( 相对于目录描述符的路径 )和/或 follow_symlinks(不遵循符号链接):[X175X ]access()、chflags()、chmod()、chown()、link()、 ]lstat()、mkdir()、mkfifo()、mknod()、open()[X356X]、[X356X] ]readlink()、remove()、rename()、replace()、rmdir()、 ]stat()、symlink()、unlink()、utime()。 可以通过设置 os.supports_dir_fd 和
os.supports_follows_symlinks
来检查使用这些参数的平台支持。以下函数现在支持路径参数的文件描述符:chdir()、chmod()、chown()、execve()[ X145X], listdir(), pathconf(), exists(), stat(), statvfs()[ X242X]、utime()。 可以通过 os.supports_fd 集检查平台对此的支持。
access() 接受
effective_ids
关键字参数以在访问检查中使用有效的 uid/gid 而不是真实的 uid/gid 打开。 可以通过 supports_effective_ids 集检查平台对此的支持。os 模块有两个新函数:getpriority() 和 setpriority()。 它们可用于以类似于 os.nice() 的方式获取或设置进程的优先级/优先级,但扩展到所有进程而不仅仅是当前进程。
(由 Giampaolo Rodolà 在 中提交的补丁:问题:`10784`。)
新的 os.replace() 函数允许跨平台重命名文件并覆盖目标。 使用 os.rename(),现有目标文件在 POSIX 下被覆盖,但在 Windows 下引发错误。 (由 Antoine Pitrou 在 中提供:issue:`8828`。)
stat 系列函数(stat()、fstat() 和 lstat())现在支持以纳秒精度读取文件的时间戳。 对称地,utime() 现在可以以纳秒精度写入文件时间戳。 (由 Larry Hastings 在 中提供:问题:`14127`。)
新的 os.get_terminal_size() 函数查询附加到文件描述符的终端的大小。 另见 shutil.get_terminal_size()。 (由 Zbigniew Jędrzejewski-Szmek 在 :issue:`13609` 中提供。)
- 支持 Linux 扩展属性的新函数 (:issue:`12720`):getxattr()、listxattr()、removexattr()[X138X ], setxattr()。
- 调度程序的新界面。 这些函数控制操作系统如何为进程分配 CPU 时间。 新函数:sched_get_priority_max()、sched_get_priority_min()、sched_getaffinity()、sched_getparam()、[X135(X78X]) X166X]、sched_rr_get_interval()、sched_setaffinity()、sched_setparam()、sched_setscheduler)sched_setscheduler() X312X],
- 控制文件系统的新函数:
- posix_fadvise():宣布以特定模式访问数据的意图,从而允许内核进行优化。
- posix_fallocate():确保为文件分配足够的磁盘空间。
- sync():强制将所有内容写入磁盘。
- 额外的新 posix 函数:
- lockf():在打开的文件描述符上应用、测试或移除 POSIX 锁。
- pread():从一个偏移量的文件描述符中读取,文件偏移量保持不变。
- pwrite():从一个偏移量写入文件描述符,保持文件偏移量不变。
- readv():从文件描述符读取到多个可写缓冲区。
- truncate():截断path对应的文件,使其大小最多为length个字节。
- waitid():等待一个或多个子进程完成。
- writev():将 buffers 的内容写入文件描述符,其中 buffers 是任意的缓冲区序列。
- getgrouplist() (:issue:`9344`):返回指定用户所属的组ID列表。
- times() 和 uname():返回类型从元组更改为具有命名属性的类元组对象。
- 某些平台现在支持 lseek() 函数的附加常量,例如
os.SEEK_HOLE
和os.SEEK_DATA
。 - 新常量 RTLD_LAZY、RTLD_NOW、RTLD_GLOBAL、RTLD_LOCAL、RTLD_NODELETE[X1135X]、[XRTLD_NOW、和 RTLD_DEEPBIND 在支持它们的平台上可用。 这些用于 sys.setdlopenflags() 函数,并取代 ctypes 和
DLFCN
中定义的类似常量。 (由 Victor Stinner 在 中提供:问题:`13226`。) - os.symlink() 现在接受(并忽略)非 Windows 平台上的
target_is_directory
关键字参数,以简化跨平台支持。
泡菜
pickle.Pickler 对象现在有一个可选的 dispatch_table 属性,允许设置每个pickler 的减少功能。
(由 Richard Oudkerk 在 :issue:`14166` 中提供。)
计划
- run() 现在接受 blocking 参数,当设置为 false 时,该方法会执行由于最快到期(如果有)而导致的计划事件,然后立即返回。 如果您想在非阻塞应用程序中使用 调度程序 ,这很有用。 (由 Giampaolo Rodolà 在 :issue:`13449` 中提供。)
- scheduler 类现在可以在多线程环境中安全使用。 (由 Josiah Carlson 和 Giampaolo Rodolà 在 中提供:issue:`8684`。)
- scheduler 类构造函数的 timefunc 和 delayfunct 参数现在是可选的,默认为 time.time() 和 time.sleep () 分别。 (由 Chris Clark 在 :issue:`13245` 中提供。)
- enter() 和 enterabs() argument 参数现在是可选的。 (由 Chris Clark 在 :issue:`13245` 中提供。)
- enter() 和 enterabs() 现在接受 kwargs 参数。 (由 Chris Clark 在 :issue:`13245` 中提供。)
选择
Solaris 和衍生平台有一个新类 select.devpoll,用于通过 /dev/poll
实现高性能异步套接字。 (由 Jesús Cea Avión 在 :issue:`6397` 中提供。)
休蒂尔
- 新功能:
- disk_usage():提供总、已用和可用磁盘空间统计信息。 (由 Giampaolo Rodolà 在 :issue:`12442` 中提供。)
- chown():允许更改给定路径的用户和/或组,同时指定用户/组名称,而不仅仅是它们的数字 ID。 (由 Sandro Tosi 在 中提供:issue:`12191`。)
- shutil.get_terminal_size():返回解释器附加到的终端窗口的大小。 (由 Zbigniew Jędrzejewski-Szmek 在 :issue:`13609` 中提供。)
- 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` 中提供。)
信号
- 信号模块新增功能:
- pthread_sigmask():获取和/或更改调用线程的信号掩码(由 Jean-Paul Calderone 在 :issue:`8407` 中贡献);
- pthread_kill():向线程发送信号;
- sigpending():检查挂起的函数;
- sigwait():等待一个信号;
- sigwaitinfo():等待一个信号,返回它的详细信息;
- sigtimedwait():类似于 sigwaitinfo() 但有超时。
- 信号处理程序将信号编号作为单个字节而不是空字节写入唤醒文件描述符。 因此,可以等待多个信号并知道发出了哪些信号。
- signal.signal() 和 signal.siginterrupt() 引发 OSError,而不是 RuntimeError:OSError 有一个 errno 属性。
smtpd
smtpd 模块现在支持 [X39X]RFC 5321(扩展 SMTP)和 RFC 1870(尺寸扩展)。 根据标准,当且仅当客户端使用 EHLO
命令启动会话时,才会启用这些扩展。
(Alberto Trevino 最初支持 ELHO
。 Juhana Jauhiainen 的尺寸扩展。 Michele Orrù 和 Dan Boswell 对补丁进行了大量额外工作。 :问题:`8739`)
smtplib
SMTP、SMTP_SSL 和 LMTP 类现在接受 source_address
关键字参数来指定 (host, port)
用作创建传出套接字时绑定调用中的源地址。 (由 Paulo Scardine 在 :issue:`11281` 中提供。)
SMTP 现在支持上下文管理协议,允许在 with
语句中使用 SMTP
实例。 (由 Giampaolo Rodolà 在 中提供:issue:`11289`。)
SMTP_SSL 构造函数和 starttls() 方法现在接受 SSLContext 参数来控制安全通道的参数。 (由 Kasun Herath 在 中提供:issue:`8809`。)
插座
socket 类现在公开了额外的方法来处理底层平台支持的辅助数据:
(由 David Watson 在 :issue:`6560` 中贡献,基于 Heiko Wundram 的早期补丁)
socket 类现在在 Linux (https://lwn.net) 上支持 PF_CAN 协议系列 (https://en.wikipedia.org/wiki/Socketcan) /文章/253425)。
(由 Matthias Fuchs 提供,由 Tiago Gonçalves 在 :issue:`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 在 :issue:`13777` 中贡献。)如果调用进程有足够的权限,新函数 sethostname() 允许在 unix 系统上设置主机名。 (由 Ross Lagerwall 在 :issue:`10866` 中贡献。)
套接字服务器
BaseServer 现在有一个可覆盖的方法 service_actions(),由服务循环中的 serve_forever() 方法调用。 ForkingMixIn 现在使用它来清理僵尸子进程。 (由 Justin Warkentin 在 中提供:issue:`11109`。)
sqlite3
新的 sqlite3.Connection 方法 set_trace_callback() 可用于捕获由 sqlite 处理的所有 sql 命令的跟踪。 (由 Torsten Landschoff 在 中提供:issue:`11688`。)
ssl
ssl 模块有两个新的随机生成函数:
RAND_bytes():生成加密强的伪随机字节。
RAND_pseudo_bytes():生成伪随机字节。
(由 Victor Stinner 在 中提供:问题:`12049`。)
ssl 模块现在公开了更细粒度的异常层次结构,以便更轻松地检查各种错误。 (由 Antoine Pitrou 在 中提供:issue:`11183`。)
load_cert_chain() 现在接受 password 参数,如果私钥被加密,则使用该参数。 (由 Adam Simpkins 在 :issue:`12803` 中贡献。)
现在通过 load_dh_params() 和 set_ecdh_curve() 方法支持常规和基于椭圆曲线的 Diffie-Hellman 密钥交换。 (由 Antoine Pitrou 在 :issue:`13626` 和 :issue:`13627` 中贡献。)
SSL 套接字具有新的 get_channel_binding() 方法,允许实施某些身份验证机制,例如 SCRAM-SHA-1-PLUS。 (由 Jacek Konieczny 在 :issue:`12551` 中提供。)
由于其新的 compression() 方法,您可以查询 SSL 套接字使用的 SSL 压缩算法。 新属性 OP_NO_COMPRESSION 可用于禁用压缩。 (由 Antoine Pitrou 在 中提供:issue:`13634`。)
使用 ssl.SSLContext.set_npn_protocols() 方法添加了对 Next Protocol Negotiation 扩展的支持。 (由 Colin Marc 在 中提供:issue:`14204`。)
由于 library 和 reason 属性,现在可以更轻松地自省 SSL 错误。 (由 Antoine Pitrou 在 中提供:issue:`14837`。)
get_server_certificate() 函数现在支持 IPv6。 (由 Charles-François Natali 在 :issue:`11811` 中提供。)
新属性 OP_CIPHER_SERVER_PREFERENCE 允许将 SSLv3 服务器套接字设置为使用服务器的密码排序首选项而不是客户端的 (:issue:`13635`)。
状态
未记录的 tarfile.filemode 函数已移至 stat.filemode()。 它可用于将文件的模式转换为“-rwxrwxrwx”形式的字符串。
(由 Giampaolo Rodolà 在 中提供:issue:`14807`。)
子流程
命令字符串现在可以是 posix 平台上的字节对象。 (由 Victor Stinner 在 中提供:问题:`8513`。)
新常量 DEVNULL 允许以独立于平台的方式抑制输出。 (由 Ross Lagerwall 在 :issue:`5870` 中贡献。)
穿线
threading.Condition、threading.Semaphore、threading.BoundedSemaphore、threading.Event和threading.Timer ,所有这些曾经是返回类实例的工厂函数,现在都是类并且可以被子类化。 (由 Éric Araujo 在 :issue:`10968` 中提供。)
threading.Thread 构造函数现在接受 daemon
关键字参数来覆盖从父线程继承 daemon
标志值的默认行为 (:issue:` 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 在 中提供:问题:`10278`。)
为了提高跨平台一致性,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'))
网页浏览器
webbrowser 模块支持更多的“浏览器”:Google Chrome(命名为 chrome、chromium、chrome-browser 或 chromium-浏览器 取决于版本和操作系统),通用启动器 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
(该模块保持向后兼容性,但现在已弃用)。 此外,Element 的 iter
系列方法已经过优化(用 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`。)
构建和 C API 更改
Python 构建过程和 C API 的更改包括:
- 新增 PEP 3118 相关功能:
- PEP 393 添加了新的 Unicode 类型、宏和函数:
- 高级API:
- 低级 API:
- Py_UCS1, Py_UCS2, Py_UCS4 类型
- PyASCIIObject 和 PyCompactUnicodeObject 结构
PyUnicode_READY
PyUnicode_FromKindAndData()
- PyUnicode_AsUCS4(), PyUnicode_AsUCS4Copy()
- PyUnicode_DATA、PyUnicode_1BYTE_DATA、PyUnicode_2BYTE_DATA、PyUnicode_4BYTE_DATA
- PyUnicode_KIND 与
PyUnicode_Kind
枚举:PyUnicode_WCHAR_KIND,PyUnicode_1BYTE_KIND,PyUnicode_2BYTE3DX3PyUnicode_2BYTE1DX3X8X8 - PyUnicode_READ, PyUnicode_READ_CHAR, PyUnicode_WRITE
PyUnicode_MAX_CHAR_VALUE
- PyArg_ParseTuple 现在接受
c
格式的 bytearray (:issue:`12380`)。
已弃用
不支持的操作系统
由于缺乏维护者,不再支持 OS/2 和 VMS。
由于维护负担,不再支持将 COMSPEC
设置为 command.com
的 Windows 2000 和 Windows 平台。
在 3.2 中已弃用的 OSF 支持已被完全删除。
弃用的 Python 模块、函数和方法
- 不推荐将非空字符串传递给
object.__format__()
,并且会在 Python 3.4 中产生 TypeError (:issue:`9856`)。 unicode_internal
编解码器已被弃用,因为 PEP 393,使用 UTF-8、UTF-16(utf-16-le
或utf-16-be
]) 或 UTF-32(utf-32-le
或utf-32-be
)- ftplib.FTP.nlst() 和 ftplib.FTP.dir():使用 ftplib.FTP.mlsd()
platform.popen()
:使用子进程模块。 特别检查 用子进程模块 部分替换旧函数 (:issue:`11377`)。- :issue:`13374`:os 模块中已弃用 Windows 字节 API。 使用 Unicode 文件名,而不是字节文件名,不再依赖于 ANSI 代码页并支持任何文件名。
- :issue:`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 包:
- importlib.abc.SourceLoader.path_mtime() 现在已弃用,取而代之的是 importlib.abc.SourceLoader.path_stats() 因为字节码文件现在存储修改时间和源的大小file 字节码文件是从中编译的。
不推荐使用的 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_LENGTHPy_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()
移植到 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`: time 和 datetime: 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_path 和 sys.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.Parser 的
strict
参数,自 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.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
字符串)。(在 :issue:`14040` 中实现。)
命令行开关更改
-Q 命令行标志和相关工件已被删除。 代码检查 sys.flags.division_warning 需要更新。
(:issue:`10998`,由 Éric Araujo 提供。)
当 python 以 -S 开头时,
import site
将不再将特定于站点的路径添加到模块搜索路径中。 在以前的版本中,确实如此。(:issue:`11591`,由 Carl Meyer 提供,由 Éric Araujo 编辑。)