Python 3.7 新特性¶
- 编辑:
Elvis Pranskevichus <elvis@magic.io>
本文解释了 Python 3.7 相对于 3.6 的新功能。Python 3.7 于 2018 年 6 月 27 日发布。有关完整详细信息,请参阅 更新日志。
总结 – 发布亮点¶
新语法功能
PEP 563,延迟评估类型注解。
向后不兼容的语法更改
新库模块
新的内置功能
PEP 553,新的
breakpoint()
函数。
Python 数据模型改进
标准库的重大改进
time
模块增加了对具有纳秒分辨率的函数的支持。
CPython 实现改进
避免使用 ASCII 作为默认文本编码
PEP 552,确定性 .pyc 文件
PEP 565,改进的
DeprecationWarning
处理
C API 的改进
PEP 539,用于线程本地存储的新 C API
文档改进
此版本在许多领域都有显著的性能改进。优化部分详细列出了这些改进。
有关可能影响与以前 Python 版本兼容性的更改列表,请参阅移植到 Python 3.7部分。
新功能¶
PEP 563: 延迟评估注解¶
Python 中类型提示的出现揭示了 PEP 3107 中添加并在 PEP 526 中进一步完善的注解功能存在的两个显著可用性问题:
注解只能使用当前作用域中已有的名称,换句话说,它们不支持任何形式的前向引用;并且
注解源代码对 Python 程序的启动时间产生不利影响。
这两个问题都通过延迟评估注解来解决。编译器不是在注解定义时编译执行注解中表达式的代码,而是将注解以字符串形式存储,该字符串形式等同于相关表达式的 AST。如果需要,可以使用 typing.get_type_hints()
在运行时解析注解。在不需要此功能的常见情况下,注解存储成本更低(因为短字符串由解释器内部化),并且可以加快启动时间。
在可用性方面,注解现在支持前向引用,使以下语法有效:
class C:
@classmethod
def from_string(cls, source: str) -> C:
...
def validate_b(self, obj: B) -> bool:
...
class B:
...
由于此更改破坏了兼容性,因此在 Python 3.7 中需要使用 __future__
导入来按模块启用新行为。
from __future__ import annotations
它将在 Python 3.10 中成为默认行为。
参见
- PEP 563 – 延迟评估注解
PEP 由 Łukasz Langa 编写和实现。
PEP 538: 遗留 C 语言环境强制转换¶
Python 3 系列中持续面临的挑战是如何为处理非 Windows 平台上默认 C 或 POSIX 语言环境所暗示的“7 位 ASCII”文本编码假设确定一个合理的默认策略。
PEP 538 更新了默认解释器命令行接口,以自动将该语言环境强制转换为可用的基于 UTF-8 的语言环境,如新 PYTHONCOERCECLOCALE
环境变量的文档中所述。以这种方式自动设置 LC_CTYPE
意味着核心解释器和支持语言环境的 C 扩展(例如 readline
)都将假定使用 UTF-8 作为默认文本编码,而不是 ASCII。
PEP 11 中的平台支持定义也已更新,以将完整文本处理支持限制在适当配置的非 ASCII 语言环境。
作为此更改的一部分,当使用任何定义的强制转换目标语言环境(目前为 C.UTF-8
、C.utf8
和 UTF-8
)时,stdin
和 stdout
的默认错误处理程序现在是 surrogateescape
(而不是 strict
)。无论语言环境如何,stderr
的默认错误处理程序仍然是 backslashreplace
。
语言环境强制转换默认是静默的,但为了帮助调试可能与语言环境相关的集成问题,可以通过设置 PYTHONCOERCECLOCALE=warn
来请求显式警告(直接在 stderr
上发出)。此设置还将导致 Python 运行时在核心解释器初始化时遗留 C 语言环境仍处于活动状态时发出警告。
虽然 PEP 538 的语言环境强制转换具有影响扩展模块(例如 GNU readline
)以及子进程(包括运行非 Python 应用程序和旧版本 Python 的子进程)的好处,但它也有一个缺点,即要求运行系统上存在合适的ARGET语言环境。为了更好地处理没有合适ARGET语言环境的情况(例如在 RHEL/CentOS 7 上发生的情况),Python 3.7 还实现了 PEP 540: 强制 UTF-8 运行时模式。
参见
- PEP 538 – 将遗留 C 语言环境强制转换为基于 UTF-8 的语言环境
由 Nick Coghlan 撰写和实现。
PEP 540: 强制 UTF-8 运行时模式¶
新的 -X
utf8
命令行选项和 PYTHONUTF8
环境变量可用于启用 Python UTF-8 模式。
在 UTF-8 模式下,CPython 忽略语言环境设置,默认使用 UTF-8 编码。sys.stdin
和 sys.stdout
流的错误处理程序设置为 surrogateescape
。
强制 UTF-8 模式可用于更改嵌入式 Python 解释器中的文本处理行为,而无需更改嵌入应用程序的语言环境设置。
虽然 PEP 540 的 UTF-8 模式具有无论运行系统上可用的语言环境如何都能工作的优点,但它也有一个缺点,即对扩展模块(例如 GNU readline
)、运行非 Python 应用程序的子进程以及运行旧版本 Python 的子进程没有影响。为了降低与此类组件通信时文本数据损坏的风险,Python 3.7 还实现了 PEP 540: 强制 UTF-8 运行时模式)。
当语言环境是 C
或 POSIX
,并且 PEP 538 语言环境强制转换功能未能将其更改为基于 UTF-8 的替代方案时(无论是由于设置了 PYTHONCOERCECLOCALE=0
、设置了 LC_ALL
还是缺少合适的 TARGET 语言环境),UTF-8 模式默认启用。
参见
- PEP 540 – 添加新的 UTF-8 模式
PEP 由 Victor Stinner 编写和实现
PEP 553: 内置 breakpoint()
¶
Python 3.7 包含新的内置 breakpoint()
函数,作为进入 Python 调试器的一种简单而一致的方式。
内置 breakpoint()
调用 sys.breakpointhook()
。默认情况下,后者导入 pdb
,然后调用 pdb.set_trace()
,但通过将 sys.breakpointhook()
绑定到你选择的函数,breakpoint()
可以进入任何调试器。此外,环境变量 PYTHONBREAKPOINT
可以设置为你选择的调试器的可调用对象。设置 PYTHONBREAKPOINT=0
以完全禁用内置 breakpoint()
。
参见
- PEP 553 – 内置 breakpoint()
PEP 由 Barry Warsaw 编写和实现
PEP 539: 用于线程本地存储的新 C API¶
虽然 Python 为线程本地存储支持提供了 C API;但现有的 线程本地存储 (TLS) API 已使用 int 来表示所有平台上的 TLS 键。这对于官方支持的平台来说通常不是问题,但这既不符合 POSIX,也不具有任何实际意义上的可移植性。
PEP 539 通过向 CPython 提供新的 线程特定存储 (TSS) API 来改变这一点,该 API 取代了 CPython 解释器中现有 TLS API 的使用,同时弃用了现有 API。TSS API 使用新类型 Py_tss_t
而不是 int 来表示 TSS 键——这是一种不透明类型,其定义可能取决于底层的 TLS 实现。因此,这将允许在原生 TLS 键定义方式无法安全地转换为 int 的平台上构建 CPython。
请注意,在原生 TLS 键定义方式无法安全地转换为 int 的平台上,现有 TLS API 的所有函数都将是空操作,并立即返回失败。这清楚地表明,旧 API 在无法可靠使用的平台上不受支持,并且不会为此类支持付出任何努力。
参见
- PEP 539 – CPython 中线程本地存储的新 C-API
PEP 由 Erik M. Bray 编写;由 Masayuki Yamamoto 实现。
PEP 562: 模块属性访问的自定义¶
Python 3.7 允许在模块上定义 __getattr__()
,并在找不到模块属性时调用它。现在也允许在模块上定义 __dir__()
。
这可能很有用的典型示例是模块属性弃用和延迟加载。
参见
- PEP 562 – 模块
__getattr__
和__dir__
PEP 由 Ivan Levkivskyi 编写和实现
PEP 564: 具有纳秒分辨率的新时间函数¶
现代系统中时钟的分辨率可能超过 time.time()
函数及其变体返回的浮点数的有限精度。为了避免精度损失,PEP 564 在 time
模块中添加了六个新的“纳秒”变体,即现有计时器函数:
新函数以整数值返回纳秒数。
测量结果 表明,在 Linux 和 Windows 上,time.time_ns()
的分辨率大约是 time.time()
的 3 倍。
参见
- PEP 564 – 添加具有纳秒分辨率的新时间函数
PEP 由 Victor Stinner 编写和实现
PEP 565: 在 __main__
中显示 DeprecationWarning¶
DeprecationWarning
的默认处理方式已更改,因此这些警告再次默认显示,但仅当触发它们的代码直接在 __main__
模块中运行时。因此,单文件脚本的开发人员和交互式使用 Python 的开发人员应该再次开始看到他们使用的 API 的弃用警告,但由导入的应用程序、库和框架模块触发的弃用警告将继续默认隐藏。
由于此更改,标准库现在允许开发人员在三种不同的弃用警告行为之间进行选择:
FutureWarning
:默认始终显示,建议用于旨在由应用程序最终用户看到的警告(例如,用于已弃用的应用程序配置设置)。DeprecationWarning
:默认仅在__main__
中和运行测试时显示,建议用于旨在由其他 Python 开发人员看到的警告,其中版本升级可能导致行为更改或错误。PendingDeprecationWarning
:默认仅在运行测试时显示,用于未来版本升级将警告类别更改为DeprecationWarning
或FutureWarning
的情况。
以前,DeprecationWarning
和 PendingDeprecationWarning
都只在运行测试时可见,这意味着主要编写单文件脚本或交互式使用 Python 的开发人员可能会对其使用的 API 中的破坏性更改感到惊讶。
参见
- PEP 565 – 在 __main__ 中显示 DeprecationWarning
PEP 由 Nick Coghlan 编写和实现
PEP 560: 对 typing
模块和泛型类型的核心支持¶
最初,PEP 484 的设计方式是不会对核心 CPython 解释器引入 任何 更改。现在,类型提示和 typing
模块被社区广泛使用,因此取消了这一限制。该 PEP 引入了两个特殊方法 __class_getitem__()
和 __mro_entries__()
,这些方法现在被 typing
中的大多数类和特殊构造使用。因此,各种类型操作的速度提高了 7 倍,泛型类型可以在没有元类冲突的情况下使用,并且 typing
模块中的几个长期存在的错误得到了修复。
参见
- PEP 560 – 对 typing 模块和泛型类型的核心支持
PEP 由 Ivan Levkivskyi 编写和实现
PEP 552: 基于哈希的 .pyc 文件¶
Python 传统上通过比较源元数据(上次修改时间戳和大小)与生成时缓存文件头中保存的源元数据来检查字节码缓存文件(即 .pyc
文件)是否最新。虽然有效,但这种失效方法有其缺点。当文件系统时间戳过于粗糙时,Python 可能会错过源更新,导致用户混淆。此外,缓存文件中包含时间戳对于 可重现构建 和基于内容的构建系统来说也是一个问题。
PEP 552 扩展了 pyc 格式,允许使用源文件的哈希而不是源时间戳进行失效。此类 .pyc
文件称为“基于哈希”。默认情况下,Python 仍然使用基于时间戳的失效,并且不会在运行时生成基于哈希的 .pyc
文件。基于哈希的 .pyc
文件可以使用 py_compile
或 compileall
生成。
基于哈希的 .pyc
文件有两种变体:已检查和未检查。Python 在运行时根据相应的源文件验证已检查的基于哈希的 .pyc
文件,但不验证未检查的基于哈希的 pyc 文件。未检查的基于哈希的 .pyc
文件对于由 Python 外部系统(例如构建系统)负责保持 .pyc
文件最新环境来说,是一种有用的性能优化。
有关更多信息,请参见 缓存字节码失效。
参见
- PEP 552 – 确定性 pyc
PEP 由 Benjamin Peterson 编写和实现
PEP 545: Python 文档翻译¶
PEP 545 描述了创建和维护 Python 文档翻译的过程。
已添加三个新翻译:
参见
- PEP 545 – Python 文档翻译
PEP 由 Julien Palard、Inada Naoki 和 Victor Stinner 编写和实现。
Python 开发模式 (-X dev)¶
新的 -X
dev
命令行选项或新的 PYTHONDEVMODE
环境变量可用于启用 Python 开发模式。在开发模式下,Python 执行额外的运行时检查,这些检查默认情况下过于昂贵而无法启用。有关完整说明,请参见 Python 开发模式 文档。
其他语言更改¶
由于实现问题,
await
表达式和包含async for
子句的推导式在 格式化字符串字面量 中的表达式中是非法的。在 Python 3.7 中,此限制已解除。现在可以向函数传递超过 255 个参数,并且函数现在可以有超过 255 个参数。(由 Serhiy Storchaka 在 bpo-12844 和 bpo-18896 中贡献。)
bytes.fromhex()
和bytearray.fromhex()
现在忽略所有 ASCII 空格,而不仅仅是空格。(由 Robert Xiao 在 bpo-28927 中贡献。)str
、bytes
和bytearray
获得了对新isascii()
方法的支持,该方法可用于测试字符串或字节是否只包含 ASCII 字符。(由 INADA Naoki 在 bpo-32677 中贡献。)当
from ... import ...
失败时,ImportError
现在会显示模块名称和模块__file__
路径。(由 Matthias Bussonnier 在 bpo-29546 中贡献。)现在支持涉及通过绑定子模块到名称的绝对导入的循环导入。(由 Serhiy Storchaka 在 bpo-30024 中贡献。)
object.__format__(x, '')
现在等同于str(x)
,而不是format(str(self), '')
。(由 Serhiy Storchaka 在 bpo-28974 中贡献。)为了更好地支持动态创建堆栈跟踪,
types.TracebackType
现在可以从 Python 代码中实例化,并且tb_next
属性在 回溯 中现在可写。(由 Nathaniel J. Smith 在 bpo-30579 中贡献。)使用
-m
开关时,sys.path[0]
现在会急切地扩展到完整的起始目录路径,而不是保留为空目录(这允许在导入发生时从 当前 工作目录进行导入)。(由 Nick Coghlan 在 bpo-33053 中贡献。)新的
-X
importtime
选项或PYTHONPROFILEIMPORTTIME
环境变量可用于显示每个模块导入的时间。(由 Inada Naoki 在 bpo-31415 中贡献。)
新模块¶
contextvars¶
新的 contextvars
模块和一组 新 C API 引入了对 上下文变量 的支持。上下文变量在概念上类似于线程本地变量。与 TLS 不同,上下文变量正确支持异步代码。
asyncio
和 decimal
模块已更新,以开箱即用地使用和支持上下文变量。特别是,活动的十进制上下文现在存储在上下文变量中,这使得十进制操作可以在异步代码中使用正确的上下文。
参见
- PEP 567 – 上下文变量
PEP 由 Yury Selivanov 编写和实现
dataclasses¶
新的 dataclass()
装饰器提供了一种声明 数据类 的方式。数据类使用类变量注解描述其属性。其构造函数和其他魔术方法,例如 __repr__()
、__eq__()
和 __hash__()
,都会自动生成。
示例
@dataclass
class Point:
x: float
y: float
z: float = 0.0
p = Point(1.5, 2.5)
print(p) # produces "Point(x=1.5, y=2.5, z=0.0)"
参见
- PEP 557 – 数据类
PEP 由 Eric V. Smith 编写和实现
importlib.resources¶
新的 importlib.resources
模块提供了几个新的 API 和一个新的 ABC,用于访问、打开和读取包内的 资源。资源大致类似于包内的文件,但它们不一定是物理文件系统上的实际文件。模块加载器可以提供一个 get_resource_reader()
函数,该函数返回一个 importlib.abc.ResourceReader
实例以支持此新 API。内置文件路径加载器和 zip 文件加载器都支持此功能。
由 Barry Warsaw 和 Brett Cannon 在 bpo-32248 中贡献。
参见
importlib_resources – 适用于早期 Python 版本的 PyPI 反向移植。
改进的模块¶
argparse¶
新的 ArgumentParser.parse_intermixed_args()
方法允许混合选项和位置参数。(由 paul.j3 在 bpo-14191 中贡献。)
asyncio¶
asyncio
模块收到了许多新功能、可用性和性能改进。值得注意的更改包括:
新的 暂定
asyncio.run()
函数可用于通过自动创建和销毁事件循环从同步代码运行协程。(由 Yury Selivanov 在 bpo-32314 中贡献。)asyncio 获得了对
contextvars
的支持。loop.call_soon()
、loop.call_soon_threadsafe()
、loop.call_later()
、loop.call_at()
和Future.add_done_callback()
都有一个新的可选的仅关键字 context 参数。Tasks
现在会自动跟踪它们的上下文。有关更多详细信息,请参见 PEP 567。(由 Yury Selivanov 在 bpo-32436 中贡献。)新的
asyncio.create_task()
函数已添加,作为asyncio.get_event_loop().create_task()
的快捷方式。(由 Andrew Svetlov 在 bpo-32311 中贡献。)新的
loop.start_tls()
方法可用于将现有连接升级到 TLS。(由 Yury Selivanov 在 bpo-23749 中贡献。)新的
loop.sock_recv_into()
方法允许将数据从套接字直接读取到提供的缓冲区中,从而可以减少数据复制。(由 Antoine Pitrou 在 bpo-31819 中贡献。)新的
asyncio.current_task()
函数返回当前运行的Task
实例,新的asyncio.all_tasks()
函数返回给定循环中所有现有Task
实例的集合。Task.current_task()
和Task.all_tasks()
方法已被弃用。(由 Andrew Svetlov 在 bpo-32250 中贡献。)新的 暂定
BufferedProtocol
类允许实现具有手动控制接收缓冲区的流式协议。(由 Yury Selivanov 在 bpo-32251 中贡献。)新的
asyncio.get_running_loop()
函数返回当前正在运行的循环,如果没有循环正在运行,则会引发RuntimeError
。这与asyncio.get_event_loop()
不同,后者在没有循环运行时会 创建 一个新的事件循环。(由 Yury Selivanov 在 bpo-32269 中贡献。)新的
StreamWriter.wait_closed()
协程方法允许等待流写入器关闭。新的StreamWriter.is_closing()
方法可用于确定写入器是否正在关闭。(由 Andrew Svetlov 在 bpo-32391 中贡献。)新的
loop.sock_sendfile()
协程方法允许在可能的情况下使用os.sendfile
发送文件。(由 Andrew Svetlov 在 bpo-32410 中贡献。)新的
Future.get_loop()
和Task.get_loop()
方法返回创建任务或 future 的循环实例。Server.get_loop()
允许对asyncio.Server
对象执行相同的操作。(由 Yury Selivanov 在 bpo-32415 中和 Srinivas Reddy Thatiparthy 在 bpo-32418 中贡献。)现在可以控制
asyncio.Server
实例如何开始服务。以前,服务器在创建时会立即开始服务。新的 start_serving 关键字参数到loop.create_server()
和loop.create_unix_server()
,以及Server.start_serving()
和Server.serve_forever()
可用于将服务器实例化和服务解耦。新的Server.is_serving()
方法返回True
,如果服务器正在服务。Server
对象现在是异步上下文管理器。srv = await loop.create_server(...) async with srv: # some code # At this point, srv is closed and no longer accepts new connections.
(由 Yury Selivanov 在 bpo-32662 中贡献。)
loop.call_later()
返回的回调对象获得了新的when()
方法,该方法返回一个绝对计划回调时间戳。(由 Andrew Svetlov 在 bpo-32741 中贡献。)loop.create_datagram_endpoint()
方法增加了对 Unix 套接字的支持。(由 Quentin Dawans 在 bpo-31245 中贡献。)asyncio.open_connection()
、asyncio.start_server()
函数、loop.create_connection()
、loop.create_server()
、loop.create_accepted_socket()
方法及其相应的 UNIX 套接字变体现在接受 ssl_handshake_timeout 关键字参数。(由 Neil Aspinall 在 bpo-29970 中贡献。)新的
Handle.cancelled()
方法返回True
,如果回调被取消。(由 Marat Sharafutdinov 在 bpo-31943 中贡献。)asyncio 源已转换为使用
async
/await
语法。(由 Andrew Svetlov 在 bpo-32193 中贡献。)新的
ReadTransport.is_reading()
方法可用于确定传输的读取状态。此外,对ReadTransport.resume_reading()
和ReadTransport.pause_reading()
的调用现在是幂等的。(由 Yury Selivanov 在 bpo-32356 中贡献。)接受套接字路径的循环方法现在支持传递 类路径对象。(由 Yury Selivanov 在 bpo-32066 中贡献。)
在
asyncio
中,Linux 上的 TCP 套接字现在默认使用TCP_NODELAY
标志创建。(由 Yury Selivanov 和 Victor Stinner 在 bpo-27456 中贡献。)取消的任务中发生的异常不再被记录。(由 Yury Selivanov 在 bpo-30508 中贡献。)
新的
WindowsSelectorEventLoopPolicy
和WindowsProactorEventLoopPolicy
类。(由 Yury Selivanov 在 bpo-33792 中贡献。)
几个 asyncio
API 已弃用。
binascii¶
b2a_uu()
函数现在接受可选的 backtick 关键字参数。当它为真时,零用 '`'
而不是空格表示。(由 Xiang Zhang 在 bpo-30103 中贡献。)
calendar¶
HTMLCalendar
类具有新的类属性,可以更轻松地自定义生成的 HTML 日历中的 CSS 类。(由 Oz Tiram 在 bpo-30095 中贡献。)
collections¶
collections.namedtuple()
现在支持默认值。(由 Raymond Hettinger 在 bpo-32320 中贡献。)
compileall¶
compileall.compile_dir()
学习了新的 invalidation_mode 参数,该参数可用于启用基于哈希的 .pyc 失效。失效模式也可以在命令行上使用新的 --invalidation-mode
参数指定。(由 Benjamin Peterson 在 bpo-31650 中贡献。)
concurrent.futures¶
ProcessPoolExecutor
和 ThreadPoolExecutor
现在支持新的 initializer 和 initargs 构造函数参数。(由 Antoine Pitrou 在 bpo-21423 中贡献。)
ProcessPoolExecutor
现在可以通过新的 mp_context 参数获取多进程上下文。(由 Thomas Moreau 在 bpo-31540 中贡献。)
contextlib¶
新的 nullcontext()
是一个比 ExitStack
更简单、更快的无操作上下文管理器。(由 Jesse-Bakker 在 bpo-10049 中贡献。)
新的 asynccontextmanager()
、AbstractAsyncContextManager
和 AsyncExitStack
已添加,以补充其同步对应物。(由 Jelle Zijlstra 在 bpo-29679 和 bpo-30241 中,以及由 Alexander Mohr 和 Ilya Kulakov 在 bpo-29302 中贡献。)
cProfile¶
cProfile
命令行现在接受 -m module_name
作为脚本路径的替代方案。(由 Sanyam Khurana 在 bpo-21862 中贡献。)
crypt¶
crypt
模块现在支持 Blowfish 哈希方法。(由 Serhiy Storchaka 在 bpo-31664 中贡献。)
mksalt()
函数现在允许指定哈希的轮数。(由 Serhiy Storchaka 在 bpo-31702 中贡献。)
datetime¶
新的 datetime.fromisoformat()
方法从 datetime.isoformat()
输出的格式之一的字符串构造一个 datetime
对象。(由 Paul Ganssle 在 bpo-15873 中贡献。)
dbm¶
dbm.dumb
现在支持读取只读文件,并且在索引文件未更改时不再写入索引文件。
decimal¶
decimal
模块现在使用上下文变量来存储十进制上下文。(由 Yury Selivanov 在 bpo-32630 中贡献。)
dis¶
dis()
函数现在能够反汇编嵌套的代码对象(推导式、生成器表达式和嵌套函数的代码,以及用于构建嵌套类的代码)。反汇编递归的最大深度由新的 depth 参数控制。(由 Serhiy Storchaka 在 bpo-11822 中贡献。)
distutils¶
README.rst
现在包含在 distutils 标准 README 列表中,因此包含在源发行版中。(由 Ryan Gonzalez 在 bpo-11913 中贡献。)
enum¶
Enum
学习了新的 _ignore_
类属性,该属性允许列出不应成为枚举成员的属性名称。(由 Ethan Furman 在 bpo-31801 中贡献。)
在 Python 3.8 中,尝试检查 Enum
类中的非 Enum 对象将引发 TypeError
(例如 1 in Color
);类似地,尝试检查 Flag
成员中的非 Flag 对象将引发 TypeError
(例如 1 in Perm.RW
);目前,这两个操作都返回 False
并已弃用。(由 Ethan Furman 在 bpo-33217 中贡献。)
functools¶
functools.singledispatch()
现在支持使用类型注解注册实现。(由 Łukasz Langa 在 bpo-32227 中贡献。)
gc¶
新的 gc.freeze()
函数允许冻结垃圾回收器跟踪的所有对象,并将其从未来的回收中排除。这可以在 POSIX fork()
调用之前使用,以使 GC 对写时复制友好或加快回收速度。新的 gc.unfreeze()
函数反转此操作。此外,gc.get_freeze_count()
可用于获取冻结对象的数量。(由 Li Zekun 在 bpo-31558 中贡献。)
hmac¶
hmac
模块现在有一个优化的单次 digest()
函数,其速度比 HMAC()
快三倍。(由 Christian Heimes 在 bpo-32433 中贡献。)
http.client¶
HTTPConnection
和 HTTPSConnection
现在支持新的 blocksize 参数,以提高上传吞吐量。(由 Nir Soffer 在 bpo-31945 中贡献。)
http.server¶
SimpleHTTPRequestHandler
现在支持 HTTP If-Modified-Since
头。如果目标文件在头中指定的时间后未被修改,服务器将返回 304 响应状态。(由 Pierre Quentel 在 bpo-29654 中贡献。)
SimpleHTTPRequestHandler
接受新的 directory 参数,此外还接受新的 --directory
命令行参数。通过此参数,服务器提供指定目录,默认情况下使用当前工作目录。(由 Stéphane Wirtel 和 Julien Palard 在 bpo-28707 中贡献。)
新的 ThreadingHTTPServer
类使用线程通过 ThreadingMixIn
处理请求。当 http.server
使用 -m
运行S时使用它。(由 Julien Palard 在 bpo-31639 中贡献。)
idlelib 和 IDLE¶
自动补全的多个修复。(由 Louie Lu 在 bpo-15786 中贡献。)
模块浏览器(在文件菜单上,以前称为类浏览器)现在除了显示顶级函数和类之外,还显示嵌套函数和类。(由 Guilherme Polo, Cheryl Sabella 和 Terry Jan Reedy 在 bpo-1612262 中贡献。)
设置对话框(选项,配置 IDLE)已部分重写,以改善外观和功能。(由 Cheryl Sabella 和 Terry Jan Reedy 在多个问题中贡献。)
字体样本现在包含一系列非拉丁字符,以便用户更好地查看选择特定字体的效果。(由 Terry Jan Reedy 在 bpo-13802 中贡献。) 样本可以编辑以包含其他字符。(由 Serhiy Storchaka 在 bpo-31860 中贡献。)
以前作为扩展实现的 IDLE 功能已重新实现为普通功能。它们的设置已从“扩展”选项卡移动到其他对话框选项卡。(由 Charles Wohlganger 和 Terry Jan Reedy 在 bpo-27099 中贡献。)
编辑器代码上下文选项已修订。框显示所有上下文行,直至 maxlines。单击上下文行会将编辑器跳转到该行。自定义主题的上下文颜色已添加到设置对话框的“高亮”选项卡中。(由 Cheryl Sabella 和 Terry Jan Reedy 在 bpo-33642, bpo-33768, 和 bpo-33679 中贡献。)
在 Windows 上,一个新的 API 调用告诉 Windows tk 缩放 DPI。在 Windows 8.1+ 或 10 上,如果 Python 二进制文件的 DPI 兼容性属性保持不变,并且监视器分辨率大于 96 DPI,这将使文本和线条更清晰。否则,它应该没有影响。(由 Terry Jan Reedy 在 bpo-33656 中贡献。)
3.7.1 中的新功能
超出 N 行(默认为 50 行)的输出会被压缩成一个按钮。N 可以在“设置”对话框的“通用”页面的“PyShell”部分更改。通过右键单击输出,可以压缩更少但可能过长的行。压缩后的输出可以通过双击按钮在原地展开,或通过右键单击按钮展开到剪贴板或单独的窗口中。(由 Tal Einat 在bpo-1529353中贡献。)
以上更改已向后移植到 3.6 维护版本。
3.7.4 中的新功能
在“运行”菜单中添加“运行自定义”,以使用自定义设置运行模块。输入的任何命令行参数都将添加到 sys.argv 中。它们会重新出现在框中以进行下一次自定义运行。还可以抑制正常的 Shell 主模块重新启动。(由 Cheryl Sabella、Terry Jan Reedy 和其他人在 bpo-5680 和 bpo-37627 中贡献。)
3.7.5 中的新功能
为 IDLE 编辑器窗口添加可选的行号。除非在配置对话框的“常规”选项卡中另有设置,否则窗口在打开时没有行号。现有窗口的行号在“选项”菜单中显示和隐藏。(由 Tal Einat 和 Saimadhav Heblikar 在 bpo-17535 中贡献。)
importlib¶
importlib.abc.ResourceReader
ABC 的引入是为了支持从包中加载资源。另请参阅 importlib.resources。(由 Barry Warsaw, Brett Cannon 在 bpo-32248 中贡献。)
如果模块缺少规范,importlib.reload()
现在将引发 ModuleNotFoundError
。(由 Garvit Khatri 在 bpo-29851 中贡献。)
如果指定的父模块不是一个包(即缺少 __path__
属性),importlib.util.find_spec()
现在将引发 ModuleNotFoundError
,而不是 AttributeError
。(由 Milan Oberkirch 在 bpo-30436 中贡献。)
新的 importlib.util.source_hash()
可用于计算传入源的哈希值。一个 基于哈希值的 .pyc 文件 嵌入了此函数返回的值。
io¶
新的 TextIOWrapper.reconfigure()
方法可用于使用新设置重新配置文本流。(由 Antoine Pitrou 在 bpo-30526 和 INADA Naoki 在 bpo-15216 中贡献。)
ipaddress¶
ipaddress.IPv6Network
和 ipaddress.IPv4Network
的新方法 subnet_of()
和 supernet_of()
可用于网络包含测试。(由 Michel Albert 和 Cheryl Sabella 在 bpo-20825 中贡献。)
itertools¶
itertools.islice()
现在接受 integer-like objects
作为 start、stop 和 slice 参数。(由 Will Roberts 在 bpo-30537 中贡献。)
locale¶
locale.format_string()
的新 monetary 参数可用于使转换使用货币千位分隔符和分组字符串。(由 Garvit 在 bpo-10379 中贡献。)
在 Android 上或在 强制 UTF-8 模式 下,locale.getpreferredencoding()
函数现在总是返回 'UTF-8'
。
logging¶
Logger
实例现在可以被 pickle。(由 Vinay Sajip 在 bpo-30520 中贡献。)
新的 StreamHandler.setStream()
方法可用于在处理程序创建后替换日志流。(由 Vinay Sajip 在 bpo-30522 中贡献。)
现在可以在传递给 logging.config.fileConfig()
的配置中为处理程序构造函数指定关键字参数。(由 Preston Landers 在 bpo-31080 中贡献。)
math¶
新的 math.remainder()
函数实现了 IEEE 754 风格的余数操作。(由 Mark Dickinson 在 bpo-29962 中贡献。)
mimetypes¶
.bmp 的 MIME 类型已从 'image/x-ms-bmp'
更改为 'image/bmp'
。(由 Nitish Chandra 在 bpo-22589 中贡献。)
msilib¶
新的 Database.Close()
方法可用于关闭 MSI 数据库。(由 Berker Peksag 在 bpo-20486 中贡献。)
multiprocessing¶
新的 Process.close()
方法显式关闭进程对象并释放与之关联的所有资源。如果底层进程仍在运行,则会引发 ValueError
。(由 Antoine Pitrou 在 bpo-30596 中贡献。)
新的 Process.kill()
方法可用于在 Unix 上使用 SIGKILL
信号终止进程。(由 Vitor Pereira 在 bpo-30794 中贡献。)
Process
创建的非守护线程现在在进程退出时被加入。(由 Antoine Pitrou 在 bpo-18966 中贡献。)
os¶
os.fwalk()
现在接受 path 参数为 bytes
。(由 Serhiy Storchaka 在 bpo-28682 中贡献。)
os.scandir()
增加了对 文件描述符 的支持。(由 Serhiy Storchaka 在 bpo-25996 中贡献。)
新的 register_at_fork()
函数允许注册 Python 回调,以便在进程 fork 时执行。(由 Antoine Pitrou 在 bpo-16500 中贡献。)
添加了 os.preadv()
(结合了 os.readv()
和 os.pread()
的功能) 和 os.pwritev()
函数 (结合了 os.writev()
和 os.pwrite()
的功能)。(由 Pablo Galindo 在 bpo-31368 中贡献。)
os.makedirs()
的 mode 参数不再影响新创建的中间级别目录的文件权限位。(由 Serhiy Storchaka 在 bpo-19930 中贡献。)
os.dup2()
现在返回新的文件描述符。以前,总是返回 None
。(由 Benjamin Peterson 在 bpo-32441 中贡献。)
os.stat()
返回的结构现在在 Solaris 及其衍生产品上包含 st_fstype
属性。(由 Jesús Cea Avión 在 bpo-32659 中贡献。)
pathlib¶
新的 Path.is_mount()
方法现在在 POSIX 系统上可用,可用于确定路径是否是挂载点。(由 Cooper Ry Lees 在 bpo-30897 中贡献。)
pdb¶
pdb.set_trace()
现在接受一个可选的 header 仅关键字参数。如果给定,它会在调试开始前打印到控制台。(由 Barry Warsaw 在 bpo-31389 中贡献。)
pdb
命令行现在接受 -m module_name
作为脚本文件的替代方案。(由 Mario Corchero 在 bpo-32206 中贡献。)
py_compile¶
py_compile.compile()
– 并且通过扩展,compileall
– 现在通过无条件地为基于哈希的验证创建 .pyc
文件来遵守 SOURCE_DATE_EPOCH
环境变量。这允许在急切创建 .pyc
文件时保证 可重现构建。(由 Bernhard M. Wiedemann 在 bpo-29708 中贡献。)
pydoc¶
pydoc 服务器现在可以绑定到由新的 -n
命令行参数指定的任意主机名。(由 Feanil Patel 在 bpo-31128 中贡献。)
queue¶
新的 SimpleQueue
类是一个无界 FIFO 队列。(由 Antoine Pitrou 在 bpo-14976 中贡献。)
re¶
标志 re.ASCII
、re.LOCALE
和 re.UNICODE
可以在组的范围内设置。(由 Serhiy Storchaka 在 bpo-31690 中贡献。)
re.split()
现在支持在匹配空字符串的模式(如 r'\b'
、'^$'
或 (?=-)
)上进行拆分。(由 Serhiy Storchaka 在 bpo-25054 中贡献。)
用 re.LOCALE
标志编译的正则表达式不再依赖于编译时的 locale。Locale 设置仅在使用编译后的正则表达式时应用。(由 Serhiy Storchaka 在 bpo-30215 中贡献。)
如果正则表达式包含将来在语义上会改变的字符集构造(例如嵌套集和集合操作),则现在会发出 FutureWarning
。(由 Serhiy Storchaka 在 bpo-30349 中贡献。)
现在可以使用 copy.copy()
和 copy.deepcopy()
复制编译的正则表达式和匹配对象。(由 Serhiy Storchaka 在 bpo-10076 中贡献。)
信号¶
signal.set_wakeup_fd()
函数的新 warn_on_full_buffer 参数允许指定当唤醒缓冲区溢出时 Python 是否在 stderr 上打印警告。(由 Nathaniel J. Smith 在 bpo-30050 中贡献。)
socket¶
新的 socket.getblocking()
方法返回 True
如果套接字处于阻塞模式,否则返回 False
。(由 Yury Selivanov 在 bpo-32373 中贡献。)
新的 socket.close()
函数关闭传递的套接字文件描述符。为了在不同平台之间更好地兼容,应该使用此函数而不是 os.close()
。(由 Christian Heimes 在 bpo-32454 中贡献。)
socket
模块现在公开了 socket.TCP_CONGESTION (Linux 2.6.13)、socket.TCP_USER_TIMEOUT (Linux 2.6.37) 和 socket.TCP_NOTSENT_LOWAT (Linux 3.12) 常量。(由 Omar Sandoval 在 bpo-26273 和 Nathaniel J. Smith 在 bpo-29728 中贡献。)
已添加对 socket.AF_VSOCK
套接字的支持,以允许虚拟机与其主机之间进行通信。(由 Cathy Avery 在 bpo-27584 中贡献。)
套接字现在默认从文件描述符自动检测家族、类型和协议。(由 Christian Heimes 在 bpo-28134 中贡献。)
socketserver¶
socketserver.ThreadingMixIn.server_close
现在等待所有非守护线程完成。socketserver.ForkingMixIn.server_close
现在等待所有子进程完成。
在 socketserver.ForkingMixIn
和 socketserver.ThreadingMixIn
类中添加一个新的 socketserver.ForkingMixIn.block_on_close
类属性。将该类属性设置为 False
以获得 3.7 之前的行为。
sqlite3¶
当底层 SQLite 库版本为 3.6.11 或更高时,sqlite3.Connection
现在公开了 backup()
方法。(由 Lele Gaifax 在 bpo-27645 中贡献。)
sqlite3.connect()
的 database 参数现在接受任何 path-like object,而不仅仅是字符串。(由 Anders Lorentsen 在 bpo-31843 中贡献。)
ssl¶
ssl
模块现在使用 OpenSSL 的内置 API 而不是 match_hostname()
来检查主机名或 IP 地址。值在 TLS 握手期间进行验证。任何证书验证错误,包括主机名检查失败,现在都会引发 SSLCertVerificationError
并以适当的 TLS 警报消息中止握手。新异常包含附加信息。主机名验证可以通过 SSLContext.hostname_checks_common_name
进行自定义。(由 Christian Heimes 在 bpo-31399 中贡献。)
备注
改进的主机名检查需要兼容 OpenSSL 1.0.2 或 1.1 的 libssl 实现。因此,OpenSSL 0.9.8 和 1.0.1 不再受支持(有关更多详细信息,请参阅 平台支持移除)。ssl 模块主要兼容 LibreSSL 2.7.2 及更高版本。
ssl
模块不再在 SNI TLS 扩展中发送 IP 地址。(由 Christian Heimes 在 bpo-32185 中贡献。)
match_hostname()
不再支持部分通配符,例如 www*.example.org
。(由 Mandeep Singh 在 bpo-23033 和 Christian Heimes 在 bpo-31399 中贡献。)
ssl
模块的默认密码套件选择现在采用黑名单方法,而不是硬编码的白名单。Python 不再重新启用被 OpenSSL 安全更新阻止的密码。默认密码套件选择可以在编译时配置。(由 Christian Heimes 在 bpo-31429 中贡献。)
现在支持验证包含国际化域名 (IDN) 的服务器证书。作为此更改的一部分,SSLSocket.server_hostname
属性现在以 A-label 形式("xn--pythn-mua.org"
)存储预期主机名,而不是 U-label 形式("pythön.org"
)。(由 Nathaniel J. Smith 和 Christian Heimes 在 bpo-28414 中贡献。)
ssl
模块对 TLS 1.3 和 OpenSSL 1.1.1 提供了初步且实验性的支持。在 Python 3.7.0 发布时,OpenSSL 1.1.1 仍在开发中,TLS 1.3 尚未最终确定。TLS 1.3 握手和协议的行为与 TLS 1.2 及更早版本略有不同,请参阅 TLS 1.3。(由 Christian Heimes 在 bpo-32947, bpo-20995, bpo-29136, bpo-30622 和 bpo-33618 中贡献。)
SSLSocket
和 SSLObject
不再有公共构造函数。直接实例化从未是文档化和支持的功能。实例必须使用 SSLContext
方法 wrap_socket()
和 wrap_bio()
创建。(由 Christian Heimes 在 bpo-32951 中贡献。)
OpenSSL 1.1 设置最小和最大 TLS 协议版本的 API 可用作 SSLContext.minimum_version
和 SSLContext.maximum_version
。支持的协议由几个新标志指示,例如 HAS_TLSv1_1
。(由 Christian Heimes 在 bpo-32609 中贡献。)
添加了 ssl.SSLContext.post_handshake_auth
用于启用,以及 ssl.SSLSocket.verify_client_post_handshake()
用于启动 TLS 1.3 握手后认证。(由 Christian Heimes 在 gh-78851 中贡献。)
string¶
string.Template
现在允许您选择性地分别修改用于大括号占位符和非大括号占位符的正则表达式模式。(由 Barry Warsaw 在 bpo-1198569 中贡献。)
subprocess¶
subprocess.run()
函数接受新的 capture_output 关键字参数。当为 True 时,stdout 和 stderr 将被捕获。这等同于将 subprocess.PIPE
作为 stdout 和 stderr 参数传递。(由 Bo Bayles 在 bpo-32102 中贡献。)
subprocess.run
函数和 subprocess.Popen
构造函数现在接受 text 关键字参数作为 universal_newlines 的别名。(由 Andrew Clegg 在 bpo-31756 中贡献。)
在 Windows 上,当重定向标准句柄时,close_fds 的默认值从 False
更改为 True
。现在可以在重定向标准句柄时将 close_fds 设置为 True。参见 subprocess.Popen
。这意味着 close_fds 现在在所有受支持的平台上默认为 True
。(由 Segev Finer 在 bpo-19764 中贡献。)
subprocess 模块现在在处理 KeyboardInterrupt
期间 subprocess.call()
、subprocess.run()
或在 Popen
上下文管理器中,处理得更加优雅。它现在会等待子进程退出一小段时间,然后再继续处理 KeyboardInterrupt
异常。(由 Gregory P. Smith 在 bpo-25942 中贡献。)
sys¶
新的 sys.breakpointhook()
钩子函数由内置的 breakpoint()
调用。(由 Barry Warsaw 在 bpo-31353 中贡献。)
在 Android 上,新的 sys.getandroidapilevel()
返回构建时 Android API 版本。(由 Victor Stinner 在 bpo-28740 中贡献。)
新的 sys.get_coroutine_origin_tracking_depth()
函数返回当前协程源跟踪深度,由新的 sys.set_coroutine_origin_tracking_depth()
设置。asyncio
已转换为使用此新 API,而不是已弃用的 sys.set_coroutine_wrapper()
。(由 Nathaniel J. Smith 在 bpo-32591 中贡献。)
时间¶
PEP 564 向 time
模块添加了六个具有纳秒分辨率的新函数
已添加新的时钟标识符
time.CLOCK_BOOTTIME
(Linux):与time.CLOCK_MONOTONIC
相同,但它还包括系统挂起的时间。time.CLOCK_PROF
(FreeBSD, NetBSD 和 OpenBSD):高分辨率的每进程 CPU 定时器。time.CLOCK_UPTIME
(FreeBSD, OpenBSD):其绝对值是系统运行且未挂起的时间,提供准确的正常运行时间测量。
新的 time.thread_time()
和 time.thread_time_ns()
函数可用于获取每线程 CPU 时间测量值。(由 Antoine Pitrou 在 bpo-32025 中贡献。)
新的 time.pthread_getcpuclockid()
函数返回线程特定 CPU 时间时钟的时钟 ID。
tkinter¶
新的 tkinter.ttk.Spinbox
类现在可用。(由 Alan Moore 在 bpo-32585 中贡献。)
tracemalloc¶
tracemalloc.Traceback
的行为更像常规回溯,按从最旧到最新的顺序排序帧。Traceback.format()
现在接受负数 limit,将结果截断为 abs(limit)
最旧的帧。要获得旧行为,请使用 Traceback.format()
的新 most_recent_first 参数。(由 Jesse Bakker 在 bpo-32121 中贡献。)
types¶
新的 WrapperDescriptorType
、MethodWrapperType
、MethodDescriptorType
和 ClassMethodDescriptorType
类现在可用。(由 Manuel Krebber 和 Guido van Rossum 在 bpo-29377,以及 Serhiy Storchaka 在 bpo-32265 中贡献。)
新的 types.resolve_bases()
函数根据 PEP 560 的规定动态解析 MRO 条目。(由 Ivan Levkivskyi 在 bpo-32717 中贡献。)
unicodedata¶
内部 unicodedata
数据库已升级到使用 Unicode 11。(由 Benjamin Peterson 贡献。)
unittest¶
新的 -k
命令行选项允许按名称子字符串或 Unix shell 风格的模式过滤测试。例如,python -m unittest -k foo
运行 foo_tests.SomeTest.test_something
、bar_tests.SomeTest.test_foo
,但不运行 bar_tests.FooTest.test_something
。(由 Jonas Haag 在 bpo-32071 中贡献。)
unittest.mock¶
sentinel
属性现在在它们被 复制
或 pickle
后保留其标识。(由 Serhiy Storchaka 在 bpo-20804 中贡献。)
新的 seal()
函数允许密封 Mock
实例,这将禁止进一步创建属性模拟。密封递归地应用于所有本身是模拟的属性。(由 Mario Corchero 在 bpo-30541 中贡献。)
urllib.parse¶
urllib.parse.quote()
已从 RFC 2396 更新到 RFC 3986,默认情况下将 ~
添加到从不引用字符集。 (由 Christian Theune 和 Ratnadeep Debnath 在 bpo-16285 中贡献。)
uu¶
uu.encode()
函数现在接受一个可选的 backtick 关键字参数。当其为 True 时,零用 '`'
而不是空格表示。(由 Xiang Zhang 在 bpo-30103 中贡献。)
uuid¶
新的 UUID.is_safe
属性传递平台信息,说明生成的 UUID 是否使用多进程安全方法生成。(由 Barry Warsaw 在 bpo-22807 中贡献。)
uuid.getnode()
现在优先选择全局管理的 MAC 地址,而不是本地管理的 MAC 地址。这更好地保证了从 uuid.uuid1()
返回的 UUID 的全球唯一性。如果只有本地管理的 MAC 地址可用,则返回找到的第一个。(由 Barry Warsaw 在 bpo-32107 中贡献。)
warnings¶
默认警告过滤器的初始化已更改如下:
通过命令行选项启用的警告(包括用于
-b
和新的 CPython 特定的-X
dev
选项)总是通过sys.warnoptions
属性传递给警告机制。通过命令行或环境变量启用的警告过滤器现在具有以下优先级顺序
用于
-b
(或-bb
) 的BytesWarning
过滤器使用
-W
选项指定的任何过滤器使用
PYTHONWARNINGS
环境变量指定的任何过滤器任何其他 CPython 特定过滤器(例如,为新的
-X dev
模式添加的default
过滤器)警告机制直接定义的任何隐式过滤器
在 CPython 调试版本 中,默认情况下会显示所有警告(隐式过滤器列表为空)
(由 Nick Coghlan 和 Victor Stinner 在 bpo-20361, bpo-32043, 和 bpo-32230 中贡献。)
在单文件脚本和交互式提示符下,默认情况下再次显示弃用警告。有关详细信息,请参阅 PEP 565: 在 __main__ 中显示 DeprecationWarning。(由 Nick Coghlan 在 bpo-31975 中贡献。)
xml¶
为了缓解 DTD 和外部实体检索的问题,xml.dom.minidom
和 xml.sax
模块默认不再处理外部实体。(由 Christian Heimes 在 gh-61441 中贡献。)
xml.etree¶
ElementPath 在 find()
方法中的谓词现在可以比较当前节点的文本与 [. = "text"]
,而不仅仅是子节点中的文本。谓词还允许添加空格以提高可读性。(由 Stefan Behnel 在 bpo-31648 中贡献。)
xmlrpc.server¶
SimpleXMLRPCDispatcher.register_function()
现在可以用作装饰器。(由 Xiang Zhang 在 bpo-7769 中贡献。)
zipapp¶
函数 create_archive()
现在接受一个可选的 filter 参数,允许用户选择哪些文件应该包含在存档中。(由 Irmen de Jong 在 bpo-31072 中贡献。)
函数 create_archive()
现在接受一个可选的 compressed 参数来生成压缩存档。还添加了命令行选项 --compress
以支持压缩。(由 Zhiming Wang 在 bpo-31638 中贡献。)
zipfile¶
ZipFile
现在接受新的 compresslevel 参数来控制压缩级别。(由 Bo Bayles 在 bpo-21417 中贡献。)
ZipFile
创建的存档中的子目录现在按字母顺序存储。(由 Bernhard M. Wiedemann 在 bpo-30693 中贡献。)
C API 更改¶
已实现一个新的线程局部存储 API。有关概述,请参阅 PEP 539: 用于线程局部存储的新 C API,有关完整参考,请参阅 线程特定存储 (TSS) API。(由 Masayuki Yamamoto 在 bpo-25658 中贡献。)
新的 PyImport_GetModule()
函数返回之前导入的具有给定名称的模块。(由 Eric Snow 在 bpo-28411 中贡献。)
新的 Py_RETURN_RICHCOMPARE
宏简化了富比较函数的编写。(由 Petr Victorin 在 bpo-23699 中贡献。)
新的 Py_UNREACHABLE
宏可用于标记不可达的代码路径。(由 Barry Warsaw 在 bpo-31338 中贡献。)
tracemalloc
现在通过新的 PyTraceMalloc_Track()
和 PyTraceMalloc_Untrack()
函数公开了 C API。(由 Victor Stinner 在 bpo-30054 中贡献。)
新的 import__find__load__start 和 import__find__load__done 静态标记可用于跟踪模块导入。(由 Christian Heimes 在 bpo-31574 中贡献。)
结构 PyMemberDef
、PyGetSetDef
、PyStructSequence_Field
、PyStructSequence_Desc
和 wrapperbase
的字段 name
和 doc
现在是 const char *
类型,而不是 char *
类型。(由 Serhiy Storchaka 在 bpo-28761 中贡献。)
PyUnicode_AsUTF8AndSize()
和 PyUnicode_AsUTF8()
的结果现在是 const char *
类型,而不是 char *
类型。(由 Serhiy Storchaka 在 bpo-28769 中贡献。)
PyMapping_Keys()
、PyMapping_Values()
和 PyMapping_Items()
的结果现在始终是一个列表,而不是列表或元组。(由 Oren Milman 在 bpo-28280 中贡献。)
添加了函数 PySlice_Unpack()
和 PySlice_AdjustIndices()
。(由 Serhiy Storchaka 在 bpo-27867 中贡献。)
PyOS_AfterFork()
已被弃用,取而代之的是新函数 PyOS_BeforeFork()
、PyOS_AfterFork_Parent()
和 PyOS_AfterFork_Child()
。(由 Antoine Pitrou 在 bpo-16500 中贡献。)
作为公共 API 一部分的 PyExc_RecursionErrorInst
单例已被删除,因为其成员从未被清除,可能导致解释器终结期间的段错误。由 Xavier de Gaye 在 bpo-22898 和 bpo-30697 中贡献。
通过时区构造函数 PyTimeZone_FromOffset()
和 PyTimeZone_FromOffsetAndName()
添加了对时区的 C API 支持,并通过 PyDateTime_TimeZone_UTC
访问 UTC 单例。由 Paul Ganssle 在 bpo-10381 中贡献。
PyThread_start_new_thread()
和 PyThread_get_thread_ident()
的结果类型以及 PyThreadState_SetAsyncExc()
的 id 参数已从 long 更改为 unsigned long。(由 Serhiy Storchaka 在 bpo-6532 中贡献。)
如果第二个参数为 NULL
且 wchar_t* 字符串包含 null 字符,PyUnicode_AsWideCharString()
现在会引发 ValueError
。(由 Serhiy Storchaka 在 bpo-30708 中贡献。)
启动序列和动态内存分配器管理方面的更改意味着,长期以来记录的要求在调用大多数 C API 函数之前调用 Py_Initialize()
现在得到了更严格的依赖,未能遵守此要求可能导致嵌入式应用程序中的段错误。有关更多详细信息,请参阅本文档中的 移植到 Python 3.7 部分和 C API 文档中的 Python 初始化之前 部分。
新的 PyInterpreterState_GetID()
返回给定解释器的唯一 ID。(由 Eric Snow 在 bpo-29102 中贡献。)
当 UTF-8 模式 启用时,Py_DecodeLocale()
和 Py_EncodeLocale()
现在使用 UTF-8 编码。(由 Victor Stinner 在 bpo-29240 中贡献。)
PyUnicode_DecodeLocaleAndSize()
和 PyUnicode_EncodeLocale()
现在为 surrogateescape
错误处理程序使用当前区域设置编码。(由 Victor Stinner 在 bpo-29240 中贡献。)
PyUnicode_FindChar()
的 start 和 end 参数现在已调整为行为类似于字符串切片。(由 Xiang Zhang 在 bpo-28822 中贡献。)
构建更改¶
已删除对构建 --without-threads
的支持。threading
模块现在始终可用。(由 Antoine Pitrou 在 bpo-31370 中贡献。)
在非 OSX UNIX 平台上构建 _ctypes
模块时,不再捆绑 libffi 的完整副本以供使用。在此类平台上构建 _ctypes
时,现在需要安装 libffi 的副本。(由 Zachary Ware 在 bpo-27979 中贡献。)
Windows 构建过程不再依赖 Subversion 引入外部源,而是使用 Python 脚本从 GitHub 下载 zip 文件。如果系统中未找到 Python 3.6(通过 py -3.6
),则使用 NuGet 下载 32 位 Python 副本以用于此目的。(由 Zachary Ware 在 bpo-30450 中贡献。)
ssl
模块需要 OpenSSL 1.0.2 或 1.1 兼容的 libssl。OpenSSL 1.0.1 已于 2016-12-31 停止生命周期,不再受支持。LibreSSL 也暂时不受支持。LibreSSL 发布版本至 2.6.4 缺少所需的 OpenSSL 1.0.2 API。
优化¶
通过将更多代码移植到使用 METH_FASTCALL
约定,C 中实现的各种标准库类的许多方法调用的开销已显著降低。(由 Victor Stinner 在 bpo-29300、bpo-29507、bpo-29452 和 bpo-29286 中贡献。)
各种优化使 Python 在 Linux 上的启动时间减少了 10%,在 macOS 上减少了 30%。(由 Victor Stinner、INADA Naoki 在 bpo-29585 中,以及 Ivan Levkivskyi 在 bpo-31333 中贡献。)
由于字节码的更改避免了创建绑定方法实例,方法调用现在快了 20%。(由 Yury Selivanov 和 INADA Naoki 在 bpo-26110 中贡献。)
asyncio
模块对常用函数进行了一系列显著优化。
asyncio.get_event_loop()
函数已用 C 重新实现,使其速度提高了 15 倍。(由 Yury Selivanov 在 bpo-32296 中贡献。)asyncio.Future
回调管理已优化。(由 Yury Selivanov 在 bpo-32348 中贡献。)asyncio.gather()
现在速度提高了 15%。(由 Yury Selivanov 在 bpo-32355 中贡献。)当 delay 参数为零或负数时,
asyncio.sleep()
现在速度提高了 2 倍。(由 Andrew Svetlov 在 bpo-32351 中贡献。)asyncio 调试模式的性能开销已降低。(由 Antoine Pitrou 在 bpo-31970 中贡献。)
由于 PEP 560 的工作,typing
的导入时间减少了 7 倍,并且许多类型操作现在更快。(由 Ivan Levkivskyi 在 bpo-32226 中贡献。)
sorted()
和 list.sort()
已针对常见情况进行了优化,速度提高了 40-75%。(由 Elliot Gorokhovsky 在 bpo-28685 中贡献。)
dict.copy()
现在速度提高了 5.5 倍。(由 Yury Selivanov 在 bpo-31179 中贡献。)
当 name 未找到且 obj 未覆盖 object.__getattr__()
或 object.__getattribute__()
时,hasattr()
和 getattr()
现在速度提高了约 4 倍。(由 INADA Naoki 在 bpo-32544 中贡献。)
在字符串中搜索某些 Unicode 字符(如乌克兰语大写“Є”)比搜索其他字符慢了 25 倍。现在,在最坏的情况下,只慢了 3 倍。(由 Serhiy Storchaka 在 bpo-24821 中贡献。)
collections.namedtuple()
工厂已重新实现,使命名元组的创建速度提高了 4 到 6 倍。(由 Jelle Zijlstra 贡献,并由 INADA Naoki、Serhiy Storchaka 和 Raymond Hettinger 在 bpo-28638 中进一步改进。)
在常见情况下,datetime.date.fromordinal()
和 datetime.date.fromtimestamp()
现在速度提高了 30%。(由 Paul Ganssle 在 bpo-32403 中贡献。)
由于使用了 os.scandir()
,os.fwalk()
函数现在速度提高了 2 倍。(由 Serhiy Storchaka 在 bpo-25996 中贡献。)
由于使用了 os.scandir()
函数,shutil.rmtree()
函数的速度提高了 20%–40%。(由 Serhiy Storchaka 在 bpo-28564 中贡献。)
优化了 正则表达式
的不区分大小写匹配和搜索。搜索某些模式现在可以快 20 倍。(由 Serhiy Storchaka 在 bpo-30285 中贡献。)
re.compile()
现在将 flags
参数转换为 int 对象,如果它是 RegexFlag
。它现在和 Python 3.5 一样快,并且比 Python 3.6 快约 10%,具体取决于模式。(由 INADA Naoki 在 bpo-31671 中贡献。)
在重负载下,selectors.EpollSelector
、selectors.PollSelector
和 selectors.DevpollSelector
类的 modify()
方法可能快约 10%。(由 Giampaolo Rodola' 在 bpo-30014 中贡献)
常量折叠已从窥孔优化器移到新的 AST 优化器,后者能够更一致地执行优化。(由 Eugene Toder 和 INADA Naoki 在 bpo-29469 和 bpo-11549 中贡献。)
abc
中的大多数函数和方法已用 C 重写。这使得抽象基类的创建,以及对它们调用 isinstance()
和 issubclass()
速度提高了 1.5 倍。这还将 Python 启动时间缩短了 10%。(由 Ivan Levkivskyi 和 INADA Naoki 在 bpo-31333 中贡献。)
通过在不构造子类时使用快速路径构造函数,datetime.date
和 datetime.datetime
的备用构造函数获得了显著的速度提升。(由 Paul Ganssle 在 bpo-32403 中贡献。)
在某些情况下,array.array
实例的比较速度得到了显著提高。在比较包含相同整数类型值的数组时,现在速度提高了 10 到 70 倍。(由 Adrian Wielgosik 在 bpo-24700 中贡献。)
math.erf()
和 math.erfc()
函数现在在大多数平台上使用(更快的)C 库实现。(由 Serhiy Storchaka 在 bpo-26121 中贡献。)
其他 CPython 实现更改¶
通过在被追踪的帧上设置相应的新属性
f_trace_lines
和f_trace_opcodes
,追踪钩子现在可以选择不接收解释器的line
事件,并选择接收opcode
事件。(由 Nick Coghlan 在 bpo-31344 中贡献。)修复了命名空间包模块属性的一些一致性问题。命名空间模块对象现在有一个设置为
None
的__file__
(以前未设置),并且它们的__spec__.origin
也设置为None
(以前是字符串"namespace"
)。请参阅 bpo-32305。此外,命名空间模块对象的__spec__.loader
设置为与__loader__
相同的值 (以前,前者设置为None
)。请参阅 bpo-32303。locals()
字典现在以变量定义的词法顺序显示。以前,顺序是未定义的。(由 Raymond Hettinger 在 bpo-32690 中贡献。)distutils
upload
命令不再尝试将 CR 行尾字符更改为 CRLF。这修复了以 CR 等效字节结尾的 sdists 的损坏问题。(由 Bo Bayles 在 bpo-32304 中贡献。)
已弃用的 Python 行为¶
现在,在推导式和生成器表达式中,yield 表达式(yield
和 yield from
子句)已被弃用(最左侧 for
子句中的可迭代表达式除外)。这确保推导式始终立即返回适当类型的容器(而不是可能返回 生成器迭代器 对象),而生成器表达式不会尝试将其隐式输出与任何显式 yield 表达式的输出交错。在 Python 3.7 中,此类表达式在编译时会发出 DeprecationWarning
,在 Python 3.8 中这将是 SyntaxError
。(由 Serhiy Storchaka 在 bpo-10544 中贡献。)
从 object.__complex__()
返回 complex
的子类已被弃用,在未来的 Python 版本中将是一个错误。这使得 __complex__()
与 object.__int__()
和 object.__float__()
保持一致。(由 Serhiy Storchaka 在 bpo-28894 中贡献。)
已弃用的 Python 模块、函数和方法¶
aifc¶
aifc.openfp()
已被弃用,并将在 Python 3.9 中移除。请改用 aifc.open()
。(由 Brian Curtin 在 bpo-31985 中贡献。)
asyncio¶
直接 await
asyncio.Lock
实例和其他 asyncio 同步原语的支持已被弃用。必须使用异步上下文管理器来获取和释放同步资源。(由 Andrew Svetlov 在 bpo-32253 中贡献。)
asyncio.Task.current_task()
和 asyncio.Task.all_tasks()
方法已被弃用。(由 Andrew Svetlov 在 bpo-32250 中贡献。)
collections¶
在 Python 3.8 中,collections.abc
中的抽象基类将不再在常规的 collections
模块中公开。这将有助于在具体类和抽象基类之间建立更清晰的区别。(由 Serhiy Storchaka 在 bpo-25988 中贡献。)
dbm¶
dbm.dumb
现在支持读取只读文件,并且在索引文件未更改时不再写入索引文件。如果索引文件丢失并在 'r'
和 'w'
模式下重新创建,现在会发出弃用警告(在未来的 Python 版本中这将是一个错误)。(由 Serhiy Storchaka 在 bpo-28847 中贡献。)
enum¶
在 Python 3.8 中,尝试在 Enum
类中检查非 Enum 对象将引发 TypeError
(例如 1 in Color
);类似地,尝试在 Flag
成员中检查非 Flag 对象将引发 TypeError
(例如 1 in Perm.RW
);目前,这两个操作都返回 False
。(由 Ethan Furman 在 bpo-33217 中贡献。)
gettext¶
在 gettext
中使用非整数值选择复数形式现在已被弃用。它从未正确工作。(由 Serhiy Storchaka 在 bpo-28692 中贡献。)
importlib¶
在 Python 3.4 中已弃用的方法 MetaPathFinder.find_module()
(被 MetaPathFinder.find_spec()
替换)和 PathEntryFinder.find_loader()
(被 PathEntryFinder.find_spec()
替换)现在都发出 DeprecationWarning
。(由 Matthias Bussonnier 在 bpo-29576 中贡献。)
importlib.abc.ResourceLoader
ABC 已被弃用,取而代之的是 importlib.abc.ResourceReader
。
locale¶
locale.format()
已被弃用,请改用 locale.format_string()
。(由 Garvit 在 bpo-10379 中贡献。)
macpath¶
macpath
现已弃用,并将在 Python 3.8 中移除。(由 Chi Hsuan Yen 在 bpo-9850 中贡献。)
threading¶
dummy_threading
和 _dummy_thread
已被弃用。不再可能禁用线程构建 Python。请改用 threading
。(由 Antoine Pitrou 在 bpo-31370 中贡献。)
socket¶
socket.htons()
和 socket.ntohs()
中的静默参数值截断已被弃用。在未来的 Python 版本中,如果传入的参数大于 16 位,将引发异常。(由 Oren Milman 在 bpo-28332 中贡献。)
ssl¶
ssl.wrap_socket()
已被弃用。请改用 ssl.SSLContext.wrap_socket()
。(由 Christian Heimes 在 bpo-28124 中贡献。)
sunau¶
sunau.openfp()
已被弃用,并将在 Python 3.9 中移除。请改用 sunau.open()
。(由 Brian Curtin 在 bpo-31985 中贡献。)
sys¶
弃用 sys.set_coroutine_wrapper()
和 sys.get_coroutine_wrapper()
。
未文档化的 sys.callstats()
函数已被弃用,并将在未来的 Python 版本中移除。(由 Victor Stinner 在 bpo-28799 中贡献。)
wave¶
wave.openfp()
已被弃用,并将在 Python 3.9 中移除。请改用 wave.open()
。(由 Brian Curtin 在 bpo-31985 中贡献。)
已弃用的 C API 函数和类型¶
如果未设置 Py_LIMITED_API
或将其设置为 0x03050400
到 0x03060000
(不包括)之间,或者为 0x03060100
或更高,则函数 PySlice_GetIndicesEx()
将被弃用并替换为宏。(由 Serhiy Storchaka 在 bpo-27867 中贡献。)
PyOS_AfterFork()
已被弃用。请改用 PyOS_BeforeFork()
、PyOS_AfterFork_Parent()
或 PyOS_AfterFork_Child()
。(由 Antoine Pitrou 在 bpo-16500 中贡献。)
平台支持移除¶
FreeBSD 9 及更早版本不再受官方支持。
为了获得完整的 Unicode 支持,包括在扩展模块中,*nix 平台现在期望至少提供
C.UTF-8
(完整区域设置)、C.utf8
(完整区域设置)或UTF-8
(仅限LC_CTYPE
区域设置)作为基于传统ASCII
的C
区域设置的替代方案。OpenSSL 0.9.8 和 1.0.1 不再受支持,这意味着在仍使用这些版本的旧平台上构建具有 SSL/TLS 支持的 CPython 3.7 需要自定义构建选项,这些选项链接到更新版本的 OpenSSL。
值得注意的是,此问题影响 Debian 8(又称“jessie”)和 Ubuntu 14.04(又称“Trusty”)LTS Linux 发行版,因为它们默认仍使用 OpenSSL 1.0.1。
Debian 9(“stretch”)和 Ubuntu 16.04(“xenial”),以及其他 LTS Linux 发行版的最新版本(例如 RHEL/CentOS 7.5、SLES 12-SP3),使用 OpenSSL 1.0.2 或更高版本,并在默认构建配置中保持受支持。
CPython 自己的 CI 配置文件 提供了一个示例,说明如何使用 CPython 测试套件中的 SSL 兼容性测试基础架构 来构建和链接 OpenSSL 1.1.0,而不是过时的系统提供的 OpenSSL。
API 和功能移除¶
以下功能和 API 已从 Python 3.7 中移除
已移除
os.stat_float_times()
函数。它在 Python 2.3 中引入,用于向后兼容 Python 2.2,并自 Python 3.1 以来已弃用。'\'
和re.sub()
替换模板中的 ASCII 字母组成的未知转义序列在 Python 3.5 中已弃用,现在将导致错误。删除了
tarfile.TarFile.add()
中 exclude 参数的支持。它在 Python 2.7 和 3.2 中已弃用。请改用 filter 参数。ntpath.splitunc()
函数在 Python 3.1 中已弃用,现已移除。请改用splitdrive()
。collections.namedtuple()
不再支持 verbose 参数或_source
属性,这些参数或属性显示了命名元组类生成的源代码。这是旨在加快类创建速度的优化的一部分。(由 Jelle Zijlstra 贡献,并由 INADA Naoki、Serhiy Storchaka 和 Raymond Hettinger 在 bpo-28638 中进一步改进。)函数
bool()
、float()
、list()
和tuple()
不再接受关键字参数。int()
的第一个参数现在只能作为位置参数传递。已移除在 Python 2.4 中已弃用的
plistlib
模块中的Plist
、Dict
和_InternalDict
类。函数readPlist()
和readPlistFromBytes()
结果中的 Dict 值现在是普通的 dict。您不再可以使用属性访问来访问这些字典的项。已移除
asyncio.windows_utils.socketpair()
函数。请改用socket.socketpair()
函数,它自 Python 3.5 以来在所有平台上都可用。asyncio.windows_utils.socketpair
在 Python 3.5 及更高版本中只是socket.socketpair
的别名。asyncio
不再将selectors
和_overlapped
模块作为asyncio.selectors
和asyncio._overlapped
导出。将from asyncio import selectors
替换为import selectors
。现在禁止直接实例化
ssl.SSLSocket
和ssl.SSLObject
对象。这些构造函数从未被文档化、测试或设计为公共构造函数。用户应该使用ssl.wrap_socket()
或ssl.SSLContext
。(由 Christian Heimes 在 bpo-32951 中贡献。)已移除未使用的
distutils
install_misc
命令。(由 Eric N. Vander Weele 在 bpo-29218 中贡献。)
模块移除¶
已移除 fpectl
模块。它从未默认启用,从未在 x86-64 上正常工作,并且它以导致 C 扩展意外损坏的方式更改了 Python ABI。(由 Nathaniel J. Smith 在 bpo-29137 中贡献。)
仅限 Windows 的更改¶
Python 启动器 (py.exe) 可以接受 32 和 64 位指定符,而无需同时指定次要版本。因此,py -3-32
和 py -3-64
变得有效,就像 py -3.7-32
一样,现在也接受 -m-64 和 -m.n-64 形式以强制使用 64 位 python,即使原本会使用 32 位。如果指定的版本不可用,py.exe 将错误退出。(由 Steve Barnes 在 bpo-30291 中贡献。)
启动器可以作为 py -0
运行,以生成已安装的 python 列表,*默认值标有星号*。运行 py -0p
将包含路径。如果 py 使用无法匹配的版本指定符运行,它还将打印可用指定符的*简短形式*列表。(由 Steve Barnes 在 bpo-30362 中贡献。)
移植到 Python 3.7¶
本节列出了前面描述过的变更以及其他可能需要修改代码的 bug 修复。
Python 行为变更¶
async
和await
名称现在是保留关键字。使用这些名称作为标识符的代码现在将引发SyntaxError
。(由 Jelle Zijlstra 在 bpo-30406 中贡献。)PEP 479 在 Python 3.7 中对所有代码启用,这意味着在协程和生成器中直接或间接引发的
StopIteration
异常将转换为RuntimeError
异常。(由 Yury Selivanov 在 bpo-32670 中贡献。)object.__aiter__()
方法不能再声明为异步。(由 Yury Selivanov 在 bpo-31709 中贡献。)由于疏忽,早期 Python 版本错误地接受了以下语法
f(1 for x in [1],) class C(1 for x in [1]): pass
Python 3.7 现在正确地引发
SyntaxError
,因为生成器表达式始终需要直接位于一组括号内,并且不能在其任一侧有逗号,并且只有在调用时才能省略重复的括号。(由 Serhiy Storchaka 在 bpo-32012 和 bpo-32023 中贡献。)当使用
-m
开关时,初始工作目录现在被添加到sys.path
中,而不是空字符串(以前它动态地表示每次导入时的当前工作目录)。任何检查空字符串或依赖先前行为的程序都需要相应地更新(例如,通过检查os.getcwd()
或os.path.dirname(__main__.__file__)
,具体取决于代码最初为什么检查空字符串)。
Python API 的变化¶
socketserver.ThreadingMixIn.server_close
现在会等待所有非守护线程完成。将新的socketserver.ThreadingMixIn.block_on_close
类属性设置为False
以获得 3.7 之前的行为。(由 Victor Stinner 在 bpo-31233 和 bpo-33540 中贡献。)socketserver.ForkingMixIn.server_close
现在会等待所有子进程完成。将新的socketserver.ForkingMixIn.block_on_close
类属性设置为False
以获得 3.7 之前的行为。(由 Victor Stinner 在 bpo-31151 和 bpo-33540 中贡献。)locale.localeconv()
函数现在在某些情况下会暂时将LC_CTYPE
区域设置设置为LC_NUMERIC
的值。(由 Victor Stinner 在 bpo-31900 中贡献。)pkgutil.walk_packages()
现在如果 path 是一个字符串,则会引发ValueError
。以前会返回一个空列表。(由 Sanyam Khurana 在 bpo-24744 中贡献。)string.Formatter.format()
的格式字符串参数现在是 仅位置参数。在 Python 3.5 中,将其作为关键字参数传递已被弃用。(由 Serhiy Storchaka 在 bpo-29193 中贡献。)类
http.cookies.Morsel
的属性key
、value
和coded_value
现在是只读的。在 Python 3.5 中,对其进行赋值已被弃用。请使用set()
方法来设置它们。(由 Serhiy Storchaka 在 bpo-29192 中贡献。)os.makedirs()
的 mode 参数不再影响新创建的中间级目录的文件权限位。要设置它们的文件权限位,您可以在调用makedirs()
之前设置 umask。(由 Serhiy Storchaka 在 bpo-19930 中贡献。)struct.Struct.format
的类型现在是str
而不是bytes
。(由 Victor Stinner 在 bpo-21071 中贡献。)cgi.parse_multipart()
现在接受 encoding 和 errors 参数,并返回与FieldStorage
相同的结果:对于非文件字段,与键关联的值是字符串列表,而不是字节。(由 Pierre Quentel 在 bpo-29979 中贡献。)由于
socket
的内部更改,不支持在旧版 Python 中对由socket.share
创建的套接字调用socket.fromshare()
。BaseException
的repr
已更改为不包含尾随逗号。大多数异常都受此更改影响。(由 Serhiy Storchaka 在 bpo-30399 中贡献。)datetime.timedelta
的repr
已更改为在输出中包含关键字参数。(由 Utkarsh Upadhyay 在 bpo-30302 中贡献。)由于
shutil.rmtree()
现在使用os.scandir()
函数实现,当列出目录失败时,用户指定的处理程序 onerror 现在将以第一个参数os.scandir
而不是os.listdir
调用。将来可能会添加对正则表达式中嵌套集和集合操作的支持,如 Unicode 技术标准 #18 中所述。这将改变语法。为了方便未来的更改,目前在模糊的情况下将引发
FutureWarning
。这包括以字面量'['
开头或包含字面量字符序列'--'
、'&&'
、'~~'
和'||'
的集合。为了避免警告,请用反斜杠转义它们。(由 Serhiy Storchaka 在 bpo-30349 中贡献。)在可能匹配空字符串的
正则表达式
上拆分字符串的结果已更改。例如,在r'\s*'
上拆分现在不仅会像以前一样在空格上拆分,还会在所有非空格字符之前和字符串末尾之前在空字符串上拆分。通过将模式更改为r'\s+'
可以恢复以前的行为。自 Python 3.5 起,对于此类模式已发出FutureWarning
。对于匹配空字符串和非空字符串的模式,在其他情况下,搜索所有匹配项的结果也可能发生变化。例如,在字符串
'a\n\n'
中,模式r'(?m)^\s*?$'
不仅会匹配位置 2 和 3 的空字符串,还会匹配位置 2-3 的字符串'\n'
。要只匹配空行,模式应重写为r'(?m)^[^\S\n]*$'
。re.sub()
现在会替换与上一个非空匹配相邻的空匹配。例如,re.sub('x*', '-', 'abxd')
现在返回'-a-b--d-'
而不是'-a-b-d-'
('b'和'd'之间的第一个减号替换'x',第二个减号替换'x'和'd'之间的空字符串)。更改
re.escape()
,使其仅转义正则表达式特殊字符,而不是转义除 ASCII 字母、数字和'_'
之外的所有字符。(由 Serhiy Storchaka 在bpo-29995中贡献。)tracemalloc.Traceback
帧现在从最旧到最新排序,以便与traceback
更一致。(由 Jesse Bakker 在bpo-32121中贡献。)在支持
socket.SOCK_NONBLOCK
或socket.SOCK_CLOEXEC
位标志的操作系统上,socket.type
不再应用它们。因此,像if sock.type == socket.SOCK_STREAM
这样的检查在所有平台上都能按预期工作。(由 Yury Selivanov 在bpo-32331中贡献。)在 Windows 上,当重定向标准句柄时,
subprocess.Popen
的close_fds参数的默认值从False
更改为True
。如果您以前在使用subprocess.Popen
进行标准 I/O 重定向时依赖于句柄的继承,则必须传入close_fds=False
以保留以前的行为,或者使用STARTUPINFO.lpAttributeList
。importlib.machinery.PathFinder.invalidate_caches()
——它隐式影响importlib.invalidate_caches()
——现在删除sys.path_importer_cache
中设置为None
的条目。(由 Brett Cannon 在bpo-33169中贡献。)在
asyncio
中,loop.sock_recv()
、loop.sock_sendall()
、loop.sock_accept()
、loop.getaddrinfo()
、loop.getnameinfo()
已更改为适当的协程方法,以符合其文档。以前,这些方法返回asyncio.Future
实例。(由 Yury Selivanov 在bpo-32327中贡献。)asyncio.Server.sockets
现在返回服务器套接字内部列表的副本,而不是直接返回它。(由 Yury Selivanov 在bpo-32662中贡献。)Struct.format
现在是str
实例,而不是bytes
实例。(由 Victor Stinner 在bpo-21071中贡献。)argparse
子解析器现在可以通过将required=True
传递给ArgumentParser.add_subparsers()
来使其成为必需项。(由 Anthony Sottile 在bpo-26510中贡献。)ast.literal_eval()
现在更加严格。不再允许任意数字的加法和减法。(由 Serhiy Storchaka 在bpo-31778中贡献。)Calendar.itermonthdates
现在将在日期超出0001-01-01
到9999-12-31
范围时始终引发异常。为了支持无法容忍此类异常的应用程序,可以使用新的Calendar.itermonthdays3
和Calendar.itermonthdays4
。新方法返回元组,并且不受datetime.date
支持的范围限制。(由 Alexander Belopolsky 在bpo-28292中贡献。)collections.ChainMap
现在保留了底层映射的顺序。(由 Raymond Hettinger 在bpo-32792中贡献。)concurrent.futures.ThreadPoolExecutor
和concurrent.futures.ProcessPoolExecutor
的submit()
方法现在在解释器关闭期间调用时会引发RuntimeError
。(由 Mark Nemec 在bpo-33097中贡献。)configparser.ConfigParser
构造函数现在使用read_dict()
来处理默认值,使其行为与解析器的其余部分一致。默认字典中的非字符串键和值现在被隐式转换为字符串。(由 James Tocknell 在bpo-23835中贡献。)删除了几个未文档化的内部导入。一个例子是
os.errno
不再可用;请直接使用import errno
。请注意,此类未文档化的内部导入可能随时被删除,恕不另行通知,即使是在微版本发布中也是如此。
C API 的变化¶
函数PySlice_GetIndicesEx()
对于可调整大小的序列被认为是不安全的。如果切片索引不是int
的实例,而是实现__index__()
方法的对象,则在将序列长度传递给PySlice_GetIndicesEx()
之后,序列可能会被重新调整大小。这可能导致返回超出序列长度的索引。为了避免可能的问题,请使用新函数PySlice_Unpack()
和PySlice_AdjustIndices()
。(由 Serhiy Storchaka 在bpo-27867中贡献。)
CPython 字节码变更¶
新增了两个操作码:LOAD_METHOD
和CALL_METHOD
。(由 Yury Selivanov 和 INADA Naoki 在bpo-26110中贡献。)
STORE_ANNOTATION
操作码已被移除。(由 Mark Shannon 在bpo-32550中贡献。)
仅限 Windows 的更改¶
用于覆盖sys.path
的文件现在称为<python-executable>._pth
而不是'sys.path'
。有关更多信息,请参阅查找模块。(由 Steve Dower 在bpo-28137中贡献。)
其他 CPython 实现更改¶
为未来 CPython 运行时初始化公共 API 的潜在更改做准备(有关初始但有些过时的草案,请参阅PEP 432),CPython 的内部启动和配置管理逻辑已进行大量重构。虽然这些更新旨在对嵌入式应用程序和常规 CPython CLI 的用户完全透明,但此处提及它们是因为重构更改了解释器启动期间各种操作的内部顺序,因此可能会发现以前潜在的缺陷,无论是在嵌入式应用程序中还是在 CPython 本身中。(最初由 Nick Coghlan 和 Eric Snow 作为bpo-22257的一部分贡献,并由 Nick、Eric 和 Victor Stinner 在许多其他问题中进一步更新)。一些已知受影响的细节
由于需要在调用
Py_Initialize
之前创建 Unicode 对象,嵌入式应用程序目前无法使用PySys_AddWarnOptionUnicode()
。请改用PySys_AddWarnOption()
。嵌入式应用程序使用
PySys_AddWarnOption()
添加的警告过滤器现在应该更一致地优先于解释器设置的默认过滤器
由于默认警告过滤器配置方式的更改,将Py_BytesWarningFlag
设置为大于 1 的值已不足以同时发出BytesWarning
消息并将其转换为异常。相反,必须设置该标志(首先发出警告),并添加显式的error::BytesWarning
警告过滤器以将其转换为异常。
由于编译器处理文档字符串的方式发生变化,现在仅包含文档字符串的函数体中隐式的return None
被标记为发生在文档字符串所在的同一行,而不是函数的标题行。
当前异常状态已从帧对象移动到协程。这简化了解释器,并修复了在进入或退出生成器时交换异常状态导致的一些隐秘错误。(由 Mark Shannon 在bpo-25612中贡献。)
Python 3.7.1 中的显著更改¶
从 3.7.1 开始,Py_Initialize()
现在一致地读取并尊重与Py_Main()
相同的所有环境设置(在较早的 Python 版本中,它尊重这些环境变量的一个定义不明确的子集,而在 Python 3.7.0 中,由于bpo-34247,它没有读取任何一个)。如果不需要此行为,请在调用Py_Initialize()
之前将Py_IgnoreEnvironmentFlag
设置为 1。
在 3.7.1 中,Context Variables 的 C API 已更新以使用PyObject
指针。另请参阅bpo-34762。
在 3.7.1 中,tokenize
模块现在在提供没有尾随换行符的输入时隐式发出一个NEWLINE
令牌。此行为现在与 C 词法分析器内部的行为匹配。(由 Ammar Askar 在bpo-33899中贡献。)
Python 3.7.2 中的显著更改¶
在 3.7.2 中,Windows 上的venv
不再复制原始二进制文件,而是创建名为python.exe
和pythonw.exe
的重定向脚本。这解决了所有虚拟环境都必须随每次 Python 更新而升级或重新创建的长期问题。但是,请注意此版本仍需要重新创建虚拟环境才能获得新脚本。
Python 3.7.6 中的显著更改¶
由于重大的安全问题,不再支持 asyncio.loop.create_datagram_endpoint()
的 reuse_address 参数。这是由于 SO_REUSEADDR
套接字选项在 UDP 中的行为。有关更多详细信息,请参见 loop.create_datagram_endpoint()
的文档。(由 Kyle Stanley、Antoine Pitrou 和 Yury Selivanov 在 bpo-37228 中贡献。)
Python 3.7.10 中的显著更改¶
较早的 Python 版本允许在urllib.parse.parse_qs()
和urllib.parse.parse_qsl()
中同时使用;
和&
作为查询参数分隔符。出于安全考虑,并为了符合新的 W3C 建议,这已更改为仅允许使用单个分隔符键,其中&
是默认值。此更改也影响cgi.parse()
和cgi.parse_multipart()
,因为它们内部使用了受影响的函数。有关更多详细信息,请参阅它们各自的文档。(由 Adam Goldschmidt、Senthil Kumaran 和 Ken Jin 在bpo-42967中贡献。)
Python 3.7.11 中的显著更改¶
一项安全修复程序改变了 ftplib.FTP
的行为,使其在建立被动数据通道时不再信任远程服务器发送的 IPv4 地址。我们改为重用 FTP 服务器的 IP 地址。对于需要旧行为的特殊代码,请将 FTP 实例上的 trust_server_pasv_ipv4_address
属性设置为 True
。(参见 gh-87451)
URL 部分中存在换行符或制表符可能导致某些形式的攻击。根据更新 RFC 3986 的 WHATWG 规范,解析器urllib.parse()
会从 URL 中去除 ASCII 换行符\n
、\r
和制表符\t
字符,以防止此类攻击。去除字符由新的模块级变量urllib.parse._UNSAFE_URL_BYTES_TO_REMOVE
控制。(请参阅gh-88048)
3.7.14 中的显著安全功能¶
在除了 2 (二进制)、4、8 (八进制)、16 (十六进制) 或 32 之外的基数(例如基数 10 (十进制))之间进行int
和str
的转换现在会在字符串形式的数字位数超过限制时引发ValueError
,以避免由于算法复杂度而可能导致的拒绝服务攻击。这是对CVE 2020-10735的缓解。此限制可以通过环境变量、命令行标志或sys
API 进行配置或禁用。请参阅整数字符串转换长度限制文档。默认限制是字符串形式的 4300 位数字。