Python 3.7 新特性

编辑:

Elvis Pranskevichus <elvis@magic.io>

本文解释了 Python 3.7 相对于 3.6 的新功能。Python 3.7 于 2018 年 6 月 27 日发布。有关完整详细信息,请参阅 更新日志

总结 – 发布亮点

新语法功能

  • PEP 563,延迟评估类型注解。

向后不兼容的语法更改

新库模块

新的内置功能

Python 数据模型改进

  • PEP 562,模块属性访问的自定义。

  • PEP 560,对 typing 模块和泛型类型的核心支持。

  • dict 对象的插入顺序保留特性已声明为 Python 语言规范的官方组成部分。

标准库的重大改进

CPython 实现改进

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-8C.utf8UTF-8)时,stdinstdout 的默认错误处理程序现在是 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.stdinsys.stdout 流的错误处理程序设置为 surrogateescape

强制 UTF-8 模式可用于更改嵌入式 Python 解释器中的文本处理行为,而无需更改嵌入应用程序的语言环境设置。

虽然 PEP 540 的 UTF-8 模式具有无论运行系统上可用的语言环境如何都能工作的优点,但它也有一个缺点,即对扩展模块(例如 GNU readline)、运行非 Python 应用程序的子进程以及运行旧版本 Python 的子进程没有影响。为了降低与此类组件通信时文本数据损坏的风险,Python 3.7 还实现了 PEP 540: 强制 UTF-8 运行时模式)。

当语言环境是 CPOSIX,并且 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 564time 模块中添加了六个新的“纳秒”变体,即现有计时器函数:

新函数以整数值返回纳秒数。

测量结果 表明,在 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:默认仅在运行测试时显示,用于未来版本升级将警告类别更改为 DeprecationWarningFutureWarning 的情况。

以前,DeprecationWarningPendingDeprecationWarning 都只在运行测试时可见,这意味着主要编写单文件脚本或交互式使用 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_compilecompileall 生成。

基于哈希的 .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-12844bpo-18896 中贡献。)

  • bytes.fromhex()bytearray.fromhex() 现在忽略所有 ASCII 空格,而不仅仅是空格。(由 Robert Xiao 在 bpo-28927 中贡献。)

  • strbytesbytearray 获得了对新 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 不同,上下文变量正确支持异步代码。

asynciodecimal 模块已更新,以开箱即用地使用和支持上下文变量。特别是,活动的十进制上下文现在存储在上下文变量中,这使得十进制操作可以在异步代码中使用正确的上下文。

参见

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

ProcessPoolExecutorThreadPoolExecutor 现在支持新的 initializerinitargs 构造函数参数。(由 Antoine Pitrou 在 bpo-21423 中贡献。)

ProcessPoolExecutor 现在可以通过新的 mp_context 参数获取多进程上下文。(由 Thomas Moreau 在 bpo-31540 中贡献。)

contextlib

新的 nullcontext() 是一个比 ExitStack 更简单、更快的无操作上下文管理器。(由 Jesse-Bakker 在 bpo-10049 中贡献。)

新的 asynccontextmanager()AbstractAsyncContextManagerAsyncExitStack 已添加,以补充其同步对应物。(由 Jelle Zijlstra 在 bpo-29679bpo-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 中贡献。)

tzinfo 类现在支持亚分钟偏移。(由 Alexander Belopolsky 在 bpo-5288 中贡献。)

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

HTTPConnectionHTTPSConnection 现在支持新的 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-5680bpo-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.IPv6Networkipaddress.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.ASCIIre.LOCALEre.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.ForkingMixInsocketserver.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-30622bpo-33618 中贡献。)

SSLSocketSSLObject 不再有公共构造函数。直接实例化从未是文档化和支持的功能。实例必须使用 SSLContext 方法 wrap_socket()wrap_bio() 创建。(由 Christian Heimes 在 bpo-32951 中贡献。)

OpenSSL 1.1 设置最小和最大 TLS 协议版本的 API 可用作 SSLContext.minimum_versionSSLContext.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 作为 stdoutstderr 参数传递。(由 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 564time 模块添加了六个具有纳秒分辨率的新函数

已添加新的时钟标识符

新的 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

新的 WrapperDescriptorTypeMethodWrapperTypeMethodDescriptorTypeClassMethodDescriptorType 类现在可用。(由 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_somethingbar_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.minidomxml.sax 模块默认不再处理外部实体。(由 Christian Heimes 在 gh-61441 中贡献。)

xml.etree

ElementPathfind() 方法中的谓词现在可以比较当前节点的文本与 [. = "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 中贡献。)

新的 上下文变量 功能公开了许多 新的 C API

新的 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__startimport__find__load__done 静态标记可用于跟踪模块导入。(由 Christian Heimes 在 bpo-31574 中贡献。)

结构 PyMemberDefPyGetSetDefPyStructSequence_FieldPyStructSequence_Descwrapperbase 的字段 namedoc 现在是 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-22898bpo-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 中贡献。)

如果第二个参数为 NULLwchar_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()startend 参数现在已调整为行为类似于字符串切片。(由 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-29300bpo-29507bpo-29452bpo-29286 中贡献。)

各种优化使 Python 在 Linux 上的启动时间减少了 10%,在 macOS 上减少了 30%。(由 Victor Stinner、INADA Naoki 在 bpo-29585 中,以及 Ivan Levkivskyi 在 bpo-31333 中贡献。)

由于字节码的更改避免了创建绑定方法实例,方法调用现在快了 20%。(由 Yury Selivanov 和 INADA Naoki 在 bpo-26110 中贡献。)

asyncio 模块对常用函数进行了一系列显著优化。

由于 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.EpollSelectorselectors.PollSelectorselectors.DevpollSelector 类的 modify() 方法可能快约 10%。(由 Giampaolo Rodola' 在 bpo-30014 中贡献)

常量折叠已从窥孔优化器移到新的 AST 优化器,后者能够更一致地执行优化。(由 Eugene Toder 和 INADA Naoki 在 bpo-29469bpo-11549 中贡献。)

abc 中的大多数函数和方法已用 C 重写。这使得抽象基类的创建,以及对它们调用 isinstance()issubclass() 速度提高了 1.5 倍。这还将 Python 启动时间缩短了 10%。(由 Ivan Levkivskyi 和 INADA Naoki 在 bpo-31333 中贡献。)

通过在不构造子类时使用快速路径构造函数,datetime.datedatetime.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_linesf_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 表达式(yieldyield 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 或将其设置为 0x030504000x03060000(不包括)之间,或者为 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 区域设置)作为基于传统 ASCIIC 区域设置的替代方案。

  • 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 模块中的 PlistDict_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.selectorsasyncio._overlapped 导出。将 from asyncio import selectors 替换为 import selectors

  • 现在禁止直接实例化 ssl.SSLSocketssl.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-32py -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 行为变更

  • asyncawait 名称现在是保留关键字。使用这些名称作为标识符的代码现在将引发 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-32012bpo-32023 中贡献。)

  • 当使用 -m 开关时,初始工作目录现在被添加到 sys.path 中,而不是空字符串(以前它动态地表示每次导入时的当前工作目录)。任何检查空字符串或依赖先前行为的程序都需要相应地更新(例如,通过检查 os.getcwd()os.path.dirname(__main__.__file__),具体取决于代码最初为什么检查空字符串)。

Python API 的变化

C API 的变化

函数PySlice_GetIndicesEx()对于可调整大小的序列被认为是不安全的。如果切片索引不是int的实例,而是实现__index__()方法的对象,则在将序列长度传递给PySlice_GetIndicesEx()之后,序列可能会被重新调整大小。这可能导致返回超出序列长度的索引。为了避免可能的问题,请使用新函数PySlice_Unpack()PySlice_AdjustIndices()。(由 Serhiy Storchaka 在bpo-27867中贡献。)

CPython 字节码变更

新增了两个操作码:LOAD_METHODCALL_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.exepythonw.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 (十进制))之间进行intstr的转换现在会在字符串形式的数字位数超过限制时引发ValueError,以避免由于算法复杂度而可能导致的拒绝服务攻击。这是对CVE 2020-10735的缓解。此限制可以通过环境变量、命令行标志或sys API 进行配置或禁用。请参阅整数字符串转换长度限制文档。默认限制是字符串形式的 4300 位数字。