Python 3.6 新特性

编辑:

Elvis Pranskevichus <elvis@magic.io>, Yury Selivanov <yury@magic.io>

本文介绍了 Python 3.6 相对于 3.5 的新特性。Python 3.6 于 2016 年 12 月 23 日发布。请参阅 更改日志 以获取完整的更改列表。

另请参阅

PEP 494 - Python 3.6 发布计划

摘要 – 版本亮点

新语法特性

  • PEP 498,格式化字符串字面值。

  • PEP 515,数字字面值中的下划线。

  • PEP 526,变量注解的语法。

  • PEP 525,异步生成器。

  • PEP 530:异步推导式。

新的库模块

CPython 实现改进

标准库中的重大改进

安全改进

  • 已添加新的 secrets 模块,以简化生成适用于管理帐户身份验证、令牌等密钥的加密强伪随机数的过程。

  • 在 Linux 上,os.urandom() 现在会阻塞,直到系统 urandom 熵池初始化以提高安全性。请参阅 PEP 524 以了解其原理。

  • hashlibssl 模块现在支持 OpenSSL 1.1.0。

  • 已改进 ssl 模块的默认设置和特性集。

  • hashlib 模块接收了对 BLAKE2、SHA-3 和 SHAKE 哈希算法以及 scrypt() 密钥派生函数的支持。

Windows 改进

  • PEP 528PEP 529,Windows 文件系统和控制台编码已更改为 UTF-8。

  • 当交互式使用 py.exe 启动器时,如果用户没有指定版本(通过命令行参数或配置文件),它不再优先选择 Python 2 而不是 Python 3。 Shebang 行的处理方式保持不变 - 在这种情况下,“python” 指的是 Python 2。

  • python.exepythonw.exe 已被标记为支持长路径,这意味着 260 个字符的路径限制可能不再适用。有关详细信息,请参阅 移除 MAX_PATH 限制

  • 可以添加一个 ._pth 文件来强制隔离模式,并完全指定所有搜索路径,以避免注册表和环境查找。有关更多信息,请参阅文档

  • 现在,python36.zip 文件可以作为推断 PYTHONHOME 的标志。 有关更多信息,请参阅 文档

新功能

PEP 498: 格式化字符串字面量

PEP 498 引入了一种新的字符串字面量:f-字符串,或 格式化字符串字面量

格式化字符串字面量以 'f' 为前缀,类似于 str.format() 接受的格式化字符串。它们包含用大括号包围的替换字段。替换字段是表达式,在运行时求值,然后使用 format() 协议进行格式化。

>>> name = "Fred"
>>> f"He said his name is {name}."
'He said his name is Fred.'
>>> width = 10
>>> precision = 4
>>> value = decimal.Decimal("12.34567")
>>> f"result: {value:{width}.{precision}}"  # nested fields
'result:      12.35'

另请参阅

PEP 498 – 字符串字面量插值。

PEP 由 Eric V. Smith 编写和实现。

功能文档.

PEP 526:变量注解的语法

PEP 484 引入了函数参数类型注解的标准,也称为类型提示。此 PEP 为 Python 添加了语法,用于注解变量(包括类变量和实例变量)的类型。

primes: List[int] = []

captain: str  # Note: no initial value!

class Starship:
    stats: Dict[str, int] = {}

与函数注解一样,Python 解释器不附加任何特定含义给变量注解,仅将其存储在类或模块的 __annotations__ 属性中。

与静态类型语言中的变量声明相比,注解语法的目标是通过抽象语法树和 __annotations__ 属性为第三方工具和库提供一种简单的方式来指定结构化的类型元数据。

另请参阅

PEP 526 – 变量注解的语法。

PEP 由 Ryan Gonzalez、Philip House、Ivan Levkivskyi、Lisa Roach 和 Guido van Rossum 编写。由 Ivan Levkivskyi 实现。

使用或将使用新语法的工具: mypy, pytype, PyCharm 等。

PEP 515: 数字字面量中的下划线

PEP 515 增加了在数字字面量中使用下划线以提高可读性的能力。 例如:

>>> 1_000_000_000_000_000
1000000000000000
>>> 0x_FF_FF_FF_FF
4294967295

允许在数字之间和任何基数说明符之后使用单个下划线。 不允许连续的前导、尾随或多个下划线。

字符串格式化语言现在也支持 '_' 选项,以表示使用下划线作为浮点数表示类型和整数表示类型 'd' 的千位分隔符。对于整数表示类型 'b', 'o', 'x''X',下划线将每 4 位插入一次。

>>> '{:_}'.format(1000000)
'1_000_000'
>>> '{:_x}'.format(0xFFFFFFFF)
'ffff_ffff'

另请参阅

PEP 515 – 数字字面量中的下划线。

PEP 由 Georg Brandl 和 Serhiy Storchaka 编写。

PEP 525: 异步生成器

PEP 492 为 Python 3.5 引入了对原生协程和 async / await 语法的支持。 Python 3.5 实现的一个显著限制是在同一个函数体中无法同时使用 awaityield。在 Python 3.6 中,此限制已被取消,从而可以定义异步生成器

async def ticker(delay, to):
    """Yield numbers from 0 to *to* every *delay* seconds."""
    for i in range(to):
        yield i
        await asyncio.sleep(delay)

新语法允许更快更简洁的代码。

另请参阅

PEP 525 – 异步生成器。

PEP 由 Yury Selivanov 编写和实现。

PEP 530:异步推导式

PEP 530 添加了对在列表、集合、字典推导式和生成器表达式中使用 async for 的支持。

result = [i async for i in aiter() if i % 2]

此外,所有类型的推导式都支持 await 表达式。

result = [await fun() for fun in funcs if await condition()]

另请参阅

PEP 530 – 异步推导式。

PEP 由 Yury Selivanov 编写和实现。

PEP 487:更简单的类创建自定义

现在可以在不使用元类的情况下自定义子类的创建。 每当创建新的子类时,都会在基类上调用新的 __init_subclass__ 类方法。

class PluginBase:
    subclasses = []

    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        cls.subclasses.append(cls)

class Plugin1(PluginBase):
    pass

class Plugin2(PluginBase):
    pass

为了允许从 __init_subclass__() 实现中正确调用零参数的 super(),自定义元类必须确保新的 __classcell__ 命名空间条目传播到 type.__new__ (如 创建类对象 中所述)。

另请参阅

PEP 487 – 更简单的类创建自定义。

PEP 由 Martin Teichmann 编写和实现。

功能文档

PEP 487:描述符协议增强

PEP 487 扩展了描述符协议,以包含新的可选的 __set_name__() 方法。每当定义一个新类时,都会在定义中包含的所有描述符上调用新方法,从而为它们提供对正在定义的类的引用以及在类命名空间中给描述符的名称。换句话说,描述符的实例现在可以知道描述符在所有者类中的属性名称。

class IntField:
    def __get__(self, instance, owner):
        return instance.__dict__[self.name]

    def __set__(self, instance, value):
        if not isinstance(value, int):
            raise ValueError(f'expecting integer in {self.name}')
        instance.__dict__[self.name] = value

    # this is the new initializer:
    def __set_name__(self, owner, name):
        self.name = name

class Model:
    int_field = IntField()

另请参阅

PEP 487 – 更简单的类创建自定义。

PEP 由 Martin Teichmann 编写和实现。

功能文档

PEP 519:添加文件系统路径协议

文件系统路径在历史上一直表示为 strbytes 对象。这导致编写操作文件系统路径的代码的人员假设此类对象只是这两种类型之一(表示文件描述符的 int 不算在内,因为它不是文件路径)。不幸的是,这种假设阻止了文件系统路径的替代对象表示形式(如 pathlib)与包括 Python 标准库在内的现有代码一起工作。

为了解决这种情况,定义了一个由 os.PathLike 表示的新接口。通过实现 __fspath__() 方法,一个对象表示它代表一个路径。然后,一个对象可以提供文件系统路径的底层表示形式,作为 strbytes 对象。这意味着,如果一个对象实现了 os.PathLike,或者是一个表示文件系统路径的 strbytes 对象,那么它就被认为是 路径型 的。代码可以使用 os.fspath()os.fsdecode()os.fsencode() 来显式获取路径型对象的 str 和/或 bytes 表示形式。

内置的 open() 函数已更新为接受 os.PathLike 对象,osos.path 模块中的所有相关函数,以及标准库中的大多数其他函数和类也是如此。os.DirEntry 类和 pathlib 中的相关类也已更新为实现 os.PathLike

我们希望更新用于操作文件系统路径的基本函数将导致第三方代码隐式支持所有 路径型对象,而无需任何代码更改,或者至少是非常小的更改(例如,在操作路径型对象之前,在代码开头调用 os.fspath())。

以下是一些示例,说明了新接口如何使 pathlib.Path 更容易、更透明地与现有代码一起使用

>>> import pathlib
>>> with open(pathlib.Path("README")) as f:
...     contents = f.read()
...
>>> import os.path
>>> os.path.splitext(pathlib.Path("some_file.txt"))
('some_file', '.txt')
>>> os.path.join("/a/b", pathlib.Path("c"))
'/a/b/c'
>>> import os
>>> os.fspath(pathlib.Path("some_file.txt"))
'some_file.txt'

(由 Brett Cannon、Ethan Furman、Dusty Phillips 和 Jelle Zijlstra 实现。)

另请参阅

PEP 519 – 添加文件系统路径协议

由 Brett Cannon 和 Koos Zevenhoven 编写的 PEP。

PEP 495:本地时间歧义

在世界上大多数地区,都存在过去和将来本地时钟回拨的情况。在这些时候,会引入一些时间间隔,在这些时间间隔内,本地时钟在同一天内会两次显示相同的时间。在这些情况下,本地时钟上显示的信息(或存储在 Python datetime 实例中的信息)不足以识别特定的时间点。

PEP 495 将新的 fold 属性添加到 datetime.datetimedatetime.time 类的实例中,以区分本地时间相同的两个时间点

>>> u0 = datetime(2016, 11, 6, 4, tzinfo=timezone.utc)
>>> for i in range(4):
...     u = u0 + i*HOUR
...     t = u.astimezone(Eastern)
...     print(u.time(), 'UTC =', t.time(), t.tzname(), t.fold)
...
04:00:00 UTC = 00:00:00 EDT 0
05:00:00 UTC = 01:00:00 EDT 0
06:00:00 UTC = 01:00:00 EST 1
07:00:00 UTC = 02:00:00 EST 0

对于所有实例,除了在有歧义的情况下表示第二个(按时间顺序)时间点的实例外, fold 属性的值为 0

另请参阅

PEP 495 – 本地时间歧义

由 Alexander Belopolsky 和 Tim Peters 编写的 PEP,由 Alexander Belopolsky 实现。

PEP 529:将 Windows 文件系统编码更改为 UTF-8

表示文件系统路径最好使用 str (Unicode) 而不是字节。但是,在某些情况下,使用字节就足够且正确。

在 Python 3.6 之前,在 Windows 上使用字节路径可能会导致数据丢失。进行此更改后,现在 Windows 上支持使用字节来表示路径,前提是这些字节使用 sys.getfilesystemencoding() 返回的编码进行编码,现在默认为 'utf-8'

不使用 str 来表示路径的应用程序应使用 os.fsencode()os.fsdecode() 来确保其字节得到正确编码。要恢复到以前的行为,请设置 PYTHONLEGACYWINDOWSFSENCODING 或调用 sys._enablelegacywindowsfsencoding()

有关更多信息以及可能需要的代码修改讨论,请参见 PEP 529

PEP 528:将 Windows 控制台编码更改为 UTF-8

Windows 上的默认控制台现在将接受所有 Unicode 字符,并为 Python 代码提供正确读取的 str 对象。sys.stdinsys.stdoutsys.stderr 现在默认为 utf-8 编码。

此更改仅在使用交互式控制台时适用,而在重定向文件或管道时不适用。要恢复到以前的交互式控制台使用行为,请设置 PYTHONLEGACYWINDOWSSTDIO

另请参阅

PEP 528 – 将 Windows 控制台编码更改为 UTF-8

由 Steve Dower 编写和实现的 PEP。

PEP 520:保留类属性定义顺序

类定义体中的属性具有自然的顺序:与名称在源代码中出现的顺序相同。此顺序现在保存在新类的 __dict__ 属性中。

此外,有效的默认类执行命名空间(从 type.__prepare__() 返回)现在是一个保留插入顺序的映射。

另请参阅

PEP 520 – 保留类属性定义顺序

由 Eric Snow 编写和实现的 PEP。

PEP 468:保留关键字参数顺序

函数签名中的 **kwargs 现在保证是一个保留插入顺序的映射。

另请参阅

PEP 468 – 保留关键字参数顺序

由 Eric Snow 编写和实现的 PEP。

新的 dict 实现

dict 类型现在使用基于 Raymond Hettinger 的提案 的“紧凑”表示形式,该提案 首先由 PyPy 实现。与 Python 3.5 相比,新的 dict() 的内存使用量减少了 20% 到 25%。

这种新实现的顺序保留特性被认为是实现细节,不应依赖它(将来可能会更改,但希望在更改语言规范以强制所有当前和未来的 Python 实现都具有顺序保留语义之前,在语言中保留此新字典实现几个版本;这也有助于保持与旧版本语言的向后兼容性,在旧版本语言中,仍然采用随机迭代顺序,例如 Python 3.5)。

(由 INADA Naoki 在 bpo-27350 中贡献。该想法最初由 Raymond Hettinger 提出。)

PEP 523:向 CPython 添加框架评估 API

虽然 Python 提供了广泛的支持来定制代码的执行方式,但在框架对象的评估方面,它并没有这样做。如果你想在 Python 中以某种方式拦截框架评估,除非直接操作已定义函数的函数指针,否则真的没有任何方法。

PEP 523 通过提供一个 API 使框架评估在 C 级别可插拔,从而改变了这一点。这将允许调试器和 JIT 等工具在 Python 代码开始执行之前拦截框架评估。这使得可以使用替代的 Python 代码评估实现、跟踪框架评估等。

此 API 不属于受限 C API 的一部分,并被标记为私有,以表明此 API 的使用预计将受到限制,并且仅适用于非常特定的低级用例。API 的语义将根据 Python 的需要进行更改。

另请参阅

PEP 523 – 向 CPython 添加框架评估 API

PEP 由 Brett Cannon 和 Dino Viehland 编写。

PYTHONMALLOC 环境变量

新的 PYTHONMALLOC 环境变量允许设置 Python 内存分配器并安装调试钩子。

现在可以使用 PYTHONMALLOC=debug 在发布模式下编译的 Python 上安装 Python 内存分配器的调试钩子。调试钩子的效果

  • 新分配的内存将填充字节 0xCB

  • 释放的内存将填充字节 0xDB

  • 检测违反 Python 内存分配器 API 的行为。例如,在由 PyMem_Malloc() 分配的内存块上调用 PyObject_Free()

  • 检测缓冲区起始位置之前的写入(缓冲区下溢)

  • 检测缓冲区结束位置之后的写入(缓冲区溢出)

  • 检查调用 PYMEM_DOMAIN_OBJ(例如:PyObject_Malloc())和 PYMEM_DOMAIN_MEM(例如:PyMem_Malloc())域的分配器函数时是否持有GIL

检查是否持有 GIL 也是 Python 3.6 的新特性。

有关 Python 内存分配器的调试钩子,请参阅 PyMem_SetupDebugHooks() 函数。

现在还可以强制对所有 Python 内存分配使用 C 库的 malloc() 分配器,方法是使用 PYTHONMALLOC=malloc。这在对发布模式下编译的 Python 使用 Valgrind 等外部内存调试器时很有帮助。

出错时,Python 内存分配器的调试钩子现在使用 tracemalloc 模块来获取内存块分配的跟踪记录。

使用 python3.6 -X tracemalloc=5(在跟踪中存储 5 个帧)时,缓冲区溢出的致命错误示例

Debug memory block at address p=0x7fbcd41666f8: API 'o'
    4 bytes originally requested
    The 7 pad bytes at p-7 are FORBIDDENBYTE, as expected.
    The 8 pad bytes at tail=0x7fbcd41666fc are not all FORBIDDENBYTE (0xfb):
        at tail+0: 0x02 *** OUCH
        at tail+1: 0xfb
        at tail+2: 0xfb
        at tail+3: 0xfb
        at tail+4: 0xfb
        at tail+5: 0xfb
        at tail+6: 0xfb
        at tail+7: 0xfb
    The block was made by call #1233329 to debug malloc/realloc.
    Data at p: 1a 2b 30 00

Memory block allocated at (most recent call first):
  File "test/test_bytes.py", line 323
  File "unittest/case.py", line 600
  File "unittest/case.py", line 648
  File "unittest/suite.py", line 122
  File "unittest/suite.py", line 84

Fatal Python error: bad trailing pad byte

Current thread 0x00007fbcdbd32700 (most recent call first):
  File "test/test_bytes.py", line 323 in test_hex
  File "unittest/case.py", line 600 in run
  File "unittest/case.py", line 648 in __call__
  File "unittest/suite.py", line 122 in run
  File "unittest/suite.py", line 84 in __call__
  File "unittest/suite.py", line 122 in run
  File "unittest/suite.py", line 84 in __call__
  ...

(由 Victor Stinner 在 bpo-26516bpo-26564 中贡献。)

DTrace 和 SystemTap 探测支持

现在可以构建带有 --with-dtrace 的 Python,这会为解释器中的以下事件启用静态标记

  • 函数调用/返回

  • 垃圾回收开始/完成

  • 执行的代码行。

这可以用来检测生产中运行的解释器,而无需重新编译特定的 调试版本 或提供特定于应用程序的分析/调试代码。

有关更多详细信息,请参阅 使用 DTrace 和 SystemTap 检测 CPython

当前的实现在 Linux 和 macOS 上进行了测试。将来可能会添加其他标记。

(由 Łukasz Langa 在 bpo-21590 中贡献,基于 Jesús Cea Avión、David Malcolm 和 Nikhil Benesch 的补丁。)

其他语言更改

对核心 Python 语言进行的一些较小的更改包括

  • globalnonlocal 语句现在必须在同一作用域中受影响名称的第一次使用之前以文本形式出现。以前,这是一个 SyntaxWarning

  • 现在可以将特殊方法设置为 None,以指示相应的操作不可用。例如,如果一个类将 __iter__() 设置为 None,则该类不可迭代。(由 Andrew Barnert 和 Ivan Levkivskyi 在 bpo-25958 中贡献。)

  • 重复回溯行的长序列现在被缩写为 "[Previous line repeated {count} more times]"(有关示例,请参阅 回溯)。(由 Emanuel Barry 在 bpo-26823 中贡献。)

  • 导入操作现在会在找不到模块时引发新的异常 ModuleNotFoundErrorImportError 的子类)。当前检查 ImportError 的代码(在 try-except 中)仍将正常工作。(由 Eric Snow 在 bpo-15767 中贡献。)

  • 在类创建期间从元类方法调用时,依赖于零参数 super() 的类方法现在可以正常工作。(由 Martin Teichmann 在 bpo-23722 中贡献。)

新模块

secrets

新的 secrets 模块的主要目的是提供一种可靠的方式来生成适用于管理密钥(例如帐户身份验证、令牌等)的加密强度高的伪随机值。

警告

请注意,random 模块中的伪随机生成器不应用于安全目的。在 Python 3.6+ 上使用 secrets,在 Python 3.5 及更早版本上使用 os.urandom()

另请参阅

PEP 506 – 向标准库添加 secrets 模块

PEP 由 Steven D’Aprano 编写和实现。

改进的模块

array

array.array 的耗尽迭代器现在即使在迭代数组被扩展时也将保持耗尽状态。这与其他可变序列的行为一致。

由 Serhiy Storchaka 在 bpo-26492 中贡献。

ast

已添加新的 ast.Constant AST 节点。外部 AST 优化器可以将其用于常量折叠的目的。

由 Victor Stinner 在 bpo-26146 中贡献。

asyncio

从 Python 3.6 开始,asyncio 模块不再是临时的,其 API 被认为是稳定的。

自 Python 3.5.0 以来 asyncio 模块中的显著变化 (由于临时状态,所有都向后移植到 3.5.x)

binascii

b2a_base64() 函数现在接受一个可选的 *newline* 关键字参数,以控制是否将换行符附加到返回值。(由 Victor Stinner 在 bpo-25357 中贡献。)

cmath

添加了新的 cmath.tau (τ) 常量。(由 Lisa Roach 在 bpo-12345 中贡献,有关详细信息,请参阅 PEP 628 。)

新的常量:cmath.infcmath.nanmath.infmath.nan 匹配,以及 cmath.infjcmath.nanj 与复数 repr 使用的格式匹配。(由 Mark Dickinson 在 bpo-23229 中贡献。)

collections

添加了新的 Collection 抽象基类来表示大小可迭代的容器类。(由 Ivan Levkivskyi 贡献,Neil Girdhar 在 bpo-27598 中编写文档。)

新的 Reversible 抽象基类表示也提供 __reversed__() 方法的可迭代类。(由 Ivan Levkivskyi 在 bpo-25987 中贡献。)

新的 AsyncGenerator 抽象基类表示异步生成器。(由 Yury Selivanov 在 bpo-28720 中贡献。)

namedtuple() 函数现在接受一个可选的关键字参数 *module*,当指定时,该参数用于返回的命名元组类的 __module__ 属性。(由 Raymond Hettinger 在 bpo-17941 中贡献。)

namedtuple() 的 *verbose* 和 *rename* 参数现在是仅关键字参数。(由 Raymond Hettinger 在 bpo-25628 中贡献。)

现在可以 pickle 递归 collections.deque 实例。(由 Serhiy Storchaka 在 bpo-26482 中贡献。)

concurrent.futures

ThreadPoolExecutor 类构造函数现在接受一个可选的 *thread_name_prefix* 参数,以便自定义池创建的线程的名称。(由 Gregory P. Smith 在 bpo-27664 中贡献。)

contextlib

添加了 contextlib.AbstractContextManager 类,为上下文管理器提供一个抽象基类。它为 __enter__() 提供了合理的默认实现(返回 self),并将 __exit__() 保留为一个抽象方法。在 typing 模块中添加了一个匹配的类 typing.ContextManager。(由 Brett Cannon 在 bpo-25609 中贡献。)

datetime

datetimetime 类新增了 fold 属性,用于在必要时消除本地时间的歧义。datetime 中的许多函数都已更新以支持本地时间消除歧义。有关更多信息,请参见 本地时间消除歧义 部分。(由 Alexander Belopolsky 在 bpo-24773 中贡献。)

datetime.strftime()date.strftime() 方法现在支持 ISO 8601 日期指令 %G%u%V。(由 Ashley Anderson 在 bpo-12006 中贡献。)

datetime.isoformat() 函数现在接受一个可选的 timespec 参数,该参数指定要包含的时间值的其他组件的数量。(由 Alessandro Cucci 和 Alexander Belopolsky 在 bpo-19475 中贡献。)

datetime.combine() 现在接受一个可选的 tzinfo 参数。(由 Alexander Belopolsky 在 bpo-27661 中贡献。)

decimal

新的 Decimal.as_integer_ratio() 方法返回一对整数 (n, d),表示给定的 Decimal 实例为一个分数,该分数以最简形式表示且分母为正数。

>>> Decimal('-3.14').as_integer_ratio()
(-157, 50)

(由 Stefan Krah 和 Mark Dickinson 在 bpo-25928 中贡献。)

distutils

distutils.command.sdist.sdist 中已删除 default_format 属性,formats 属性的默认值设置为 ['gztar']。尽管没有预期到,但任何依赖 default_format 存在的代码可能需要进行调整。有关更多详细信息,请参见 bpo-27819

email

通过 policy 关键字启用新的电子邮件 API(用于各种构造函数)不再是临时的。email 文档已重新组织和重写,重点介绍新的 API,同时保留旧版 API 的旧文档。(由 R. David Murray 在 bpo-24277 中贡献。)

email.mime 类现在都接受可选的 policy 关键字。(由 Berker Peksag 在 bpo-27331 中贡献。)

DecodedGenerator 现在支持 policy 关键字。

有一个新的 policy 属性 message_factory,用于控制当解析器创建新的消息对象时默认使用的类。对于 email.policy.compat32 策略,这是 Message,对于新的策略,则是 EmailMessage。(由 R. David Murray 在 bpo-20476 中贡献。)

encodings

在 Windows 上,添加了 'oem' 编码以使用 CP_OEMCP,以及现有 'mbcs' 编码的 'ansi' 别名,该编码使用 CP_ACP 代码页。(由 Steve Dower 在 bpo-27959 中贡献。)

enum

enum 模块中添加了两个新的枚举基类:FlagIntFlags。两者都用于定义可以使用按位运算符组合的常量。(由 Ethan Furman 在 bpo-23591 中贡献。)

许多标准库模块已更新为在其常量中使用 IntFlags 类。

新的 enum.auto 值可用于自动为枚举成员赋值。

>>> from enum import Enum, auto
>>> class Color(Enum):
...     red = auto()
...     blue = auto()
...     green = auto()
...
>>> list(Color)
[<Color.red: 1>, <Color.blue: 2>, <Color.green: 3>]

faulthandler

在 Windows 上,faulthandler 模块现在为 Windows 异常安装一个处理程序:请参阅 faulthandler.enable()。(由 Victor Stinner 在 bpo-23848 中贡献。)

fileinput

hook_encoded() 现在支持 errors 参数。(由 Joseph Hackman 在 bpo-25788 中贡献。)

hashlib

hashlib 支持 OpenSSL 1.1.0。最低建议版本为 1.0.2。(由 Christian Heimes 在 bpo-26470 中贡献。)

BLAKE2 哈希函数已添加到模块中。blake2b()blake2s() 始终可用,并支持 BLAKE2 的全部功能。(由 Christian Heimes 在 bpo-26798 中贡献,基于 Dmitry Chestnykh 和 Samuel Neves 的代码。Dmitry Chestnykh 编写的文档。)

添加了 SHA-3 哈希函数 sha3_224()sha3_256()sha3_384()sha3_512() 和 SHAKE 哈希函数 shake_128()shake_256()。(由 Christian Heimes 在 bpo-16113 中贡献。Keccak 代码包由 Guido Bertoni、Joan Daemen、Michaël Peeters、Gilles Van Assche 和 Ronny Van Keer 提供。)

基于密码的密钥派生函数 scrypt() 现在可用于 OpenSSL 1.1.0 及更高版本。(由 Christian Heimes 在 bpo-27928 中贡献。)

http.client

HTTPConnection.request()endheaders() 现在都支持分块编码的请求体。(由 Demian Brecht 和 Rolf Krahl 在 bpo-12319 中贡献。)

idlelib 和 IDLE

idlelib 包正在进行现代化和重构,以使 IDLE 看起来和工作起来更好,并使代码更易于理解、测试和改进。使 IDLE 看起来更好(尤其是在 Linux 和 Mac 上)的部分工作是使用 ttk 小部件,主要是在对话框中。因此,IDLE 不再与 tcl/tk 8.4 一起运行。它现在需要 tcl/tk 8.5 或 8.6。我们建议运行两者的最新版本。

“现代化”包括重命名和整合 idlelib 模块。部分大写名称文件的重命名类似于 3.0 中将 Tkinter 和 TkFont 重命名为 tkinter 和 tkinter.font。因此,在 3.5 中可以工作的 idlelib 文件的导入通常在 3.6 中无法工作。至少需要更改模块名称(请参阅 idlelib/README.txt),有时还需要更多更改。(由 Al Swiegart 和 Terry Reedy 在 bpo-24225 中贡献的名称更改。此后的大部分 idlelib 补丁都将是此过程的一部分。)

作为补偿,最终的结果是,一些 idlelib 类将更易于使用,并具有更好的 API 和解释它们的文档字符串。如有,其他有用的信息将添加到 idlelib 中。

3.6.2 中的新功能

修复了自动完成的多个问题。(由 Louie Lu 在 bpo-15786 中贡献。)

3.6.3 中的新功能

模块浏览器(在“文件”菜单上,以前称为“类浏览器”)现在除了顶级函数和类之外,还显示嵌套的函数和类。(由 Guilherme Polo、Cheryl Sabella 和 Terry Jan Reedy 在 bpo-1612262 中贡献。)

以前作为扩展实现的 IDLE 功能已重新实现为普通功能。它们的设置已从“扩展”选项卡移动到其他对话框选项卡。(由 Charles Wohlganger 和 Terry Jan Reedy 在 bpo-27099 中贡献。)

“设置”对话框(“选项”,“配置 IDLE”)已部分重写,以改进外观和功能。(由 Cheryl Sabella 和 Terry Jan Reedy 在多个问题中贡献。)

3.6.4 中的新功能

字体样本现在包含一些非拉丁字符的选择,以便用户可以更好地看到选择特定字体的效果。(由 Terry Jan Reedy 在 bpo-13802 中贡献。)可以编辑该样本以包含其他字符。(由 Serhiy Storchaka 在 bpo-31860 中贡献。)

3.6.6 中的新功能

修改了编辑器代码上下文选项。该框显示最多 maxlines 的所有上下文行。单击上下文行会将编辑器跳转到该行。“设置”对话框的“突出显示”选项卡中添加了自定义主题的上下文颜色。(由 Cheryl Sabella 和 Terry Jan Reedy 在 bpo-33642bpo-33768bpo-33679 中贡献。)

在 Windows 上,新的 API 调用告诉 Windows tk 为 DPI 缩放。在 Windows 8.1+ 或 10 上,如果 Python 二进制文件的 DPI 兼容性属性未更改,并且显示器分辨率大于 96 DPI,则应使文本和线条更清晰。否则,它应该没有影响。(由 Terry Jan Reedy 在 bpo-33656 中贡献。)

3.6.7 中的新功能

超过 N 行(默认为 50 行)的输出会压缩为一个按钮。可以在“设置”对话框的“常规”页面的“PyShell”部分中更改 N。可以通过右键单击输出来压缩较少但可能超长的行。可以通过双击按钮将压缩的输出就地展开,或者通过右键单击按钮将其展开到剪贴板或单独的窗口中。(由 Tal Einat 在 bpo-1529353 中贡献。)

importlib

当无法找到模块时,导入现在会引发新的异常 ModuleNotFoundErrorImportError 的子类)。当前检查 ImportError 的代码(在 try-except 中)仍然有效。(由 Eric Snow 在 bpo-15767 中贡献。)

importlib.util.LazyLoader 现在在包装的加载器上调用 create_module(),从而消除了 importlib.machinery.BuiltinImporterimportlib.machinery.ExtensionFileLoader 不能与 importlib.util.LazyLoader 一起使用的限制。

importlib.util.cache_from_source()importlib.util.source_from_cache()importlib.util.spec_from_file_location() 现在接受 路径类对象

inspect

inspect.signature() 函数现在将编译器为推导式和生成器表达式作用域生成的隐式 .0 参数报告为就像它们是名为 implicit0 的仅位置参数一样。(由 Jelle Zijlstra 在 bpo-19611 中贡献。)

为了减少从 Python 2.7 和旧版 inspect.getargspec() API 升级时的代码变动,之前记录的 inspect.getfullargspec() 的弃用已被撤销。虽然此函数对于单个/源 Python 2/3 代码库很方便,但更丰富的 inspect.signature() 接口仍然是新代码的推荐方法。(由 Nick Coghlan 在 bpo-27172 中贡献)

json

json.load()json.loads() 现在支持二进制输入。编码的 JSON 应使用 UTF-8、UTF-16 或 UTF-32 表示。(由 Serhiy Storchaka 在 bpo-17909 中贡献。)

logging

添加了新的 WatchedFileHandler.reopenIfNeeded() 方法,以添加检查日志文件是否需要重新打开的功能。(由 Marian Horban 在 bpo-24884 中贡献。)

math

tau (τ) 常量已添加到 mathcmath 模块。(由 Lisa Roach 在 bpo-12345 中贡献,有关详细信息,请参见 PEP 628。)

multiprocessing

multiprocessing.Manager() 返回的 代理对象 现在可以嵌套。(由 Davin Potts 在 bpo-6766 中贡献。)

os

有关 osos.path 模块现在如何支持 路径类对象 的详细信息,请参见 PEP 519 的摘要。

scandir() 现在支持 Windows 上的 bytes 路径。

新的 close() 方法允许显式关闭 scandir() 迭代器。scandir() 迭代器现在支持 上下文管理器 协议。如果 scandir() 迭代器既未耗尽也未显式关闭,则其析构函数将发出 ResourceWarning。(由 Serhiy Storchaka 在 bpo-25994 中贡献。)

在 Linux 上,os.urandom() 现在会阻塞,直到系统 urandom 熵池初始化以提高安全性。请参阅 PEP 524 了解其原理。

Linux 的 getrandom() 系统调用(获取随机字节)现在以新的 os.getrandom() 函数的形式公开。(由 Victor Stinner 贡献,是 PEP 524 的一部分)

pathlib

pathlib 现在支持 类路径对象。(由 Brett Cannon 在 bpo-27186 中贡献。)

有关详细信息,请参阅 PEP 519 的摘要。

pdb

Pdb 类构造函数有一个新的可选参数 readrc,用于控制是否应读取 .pdbrc 文件。

pickle

现在可以使用低于协议版本 4 的 pickle 协议 来封送需要使用关键字参数调用 __new__ 的对象。协议版本 4 已经支持这种情况。(由 Serhiy Storchaka 在 bpo-24164 中贡献。)

pickletools

pickletools.dis() 现在为 MEMOIZE 操作码输出隐式备忘录索引。(由 Serhiy Storchaka 在 bpo-25382 中贡献。)

pydoc

pydoc 模块已经学会尊重 MANPAGER 环境变量。(由 Matthias Klose 在 bpo-8637 中贡献。)

help()pydoc 现在可以按照定义顺序而不是字母顺序列出具名元组字段。(由 Raymond Hettinger 在 bpo-24879 中贡献。)

random

新的 choices() 函数返回一个指定大小的元素列表,这些元素来自给定的种群,并具有可选的权重。(由 Raymond Hettinger 在 bpo-18844 中贡献。)

re

在正则表达式中添加了对修饰符跨度的支持。示例:'(?i:p)ython' 匹配 'python''Python',但不匹配 'PYTHON''(?i)g(?-i:v)r' 匹配 'GvR''gvr',但不匹配 'GVR'。(由 Serhiy Storchaka 在 bpo-433028 中贡献。)

可以通过 __getitem__ 访问匹配对象组,这等效于 group()。因此,mo['name'] 现在等效于 mo.group('name')。(由 Eric Smith 在 bpo-24454 中贡献。)

Match 对象现在支持 类索引 对象 作为组索引。(由 Jeroen Demeyer 和 Xiang Zhang 在 bpo-27177 中贡献。)

readline

添加了 set_auto_history() 来启用或禁用将输入自动添加到历史列表。(由 Tyler Crompton 在 bpo-26870 中贡献。)

rlcompleter

现在,除非前缀以下划线开头,否则会省略私有和特殊属性名称。在某些已完成的关键字后添加空格或冒号。(由 Serhiy Storchaka 在 bpo-25011bpo-25209 中贡献。)

shlex

通过新的 punctuation_chars 参数来控制哪些字符被视为标点符号,shlex 具有改进的 shell 兼容性。(由 Vinay Sajip 在 bpo-1521950 中贡献。)

site

.pth 文件中指定要添加到 sys.path 的路径时,现在可以在目录之上指定文件路径(例如 zip 文件)。(由 Wolfgang Langner 在 bpo-26587 中贡献。)

sqlite3

sqlite3.Cursor.lastrowid 现在支持 REPLACE 语句。(由 Alex LordThorsen 在 bpo-16864 中贡献。)

socket

ioctl() 函数现在支持 SIO_LOOPBACK_FAST_PATH 控制码。(由 Daniel Stokes 在 bpo-26536 中贡献。)

现在支持 getsockopt() 常量 SO_DOMAINSO_PROTOCOLSO_PEERSECSO_PASSSEC。(由 Christian Heimes 在 bpo-26907 中贡献。)

setsockopt() 现在支持 setsockopt(level, optname, None, optlen: int) 形式。(由 Christian Heimes 在 bpo-27744 中贡献。)

socket 模块现在支持地址族 AF_ALG,以与 Linux 内核加密 API 接口。ALG_*SOL_ALGsendmsg_afalg() 已被添加。(由 Christian Heimes 在 bpo-27744 中贡献,并得到 Victor Stinner 的支持。)

添加了新的 Linux 常量 TCP_USER_TIMEOUTTCP_CONGESTION。(由 Omar Sandoval 贡献,bpo-26273)。

socketserver

基于 socketserver 模块的服务器,包括在 http.serverxmlrpc.serverwsgiref.simple_server 中定义的服务器,现在支持 上下文管理器 协议。(由 Aviv Palivoda 在 bpo-26404 中贡献。)

StreamRequestHandler 类的 wfile 属性现在实现了 io.BufferedIOBase 可写接口。特别是,现在保证调用 write() 会完整发送数据。(由 Martin Panter 在 bpo-26721 中贡献。)

ssl

ssl 支持 OpenSSL 1.1.0。建议的最低版本为 1.0.2。(由 Christian Heimes 在 bpo-26470 中贡献。)

3DES 已从默认密码套件中删除,并添加了 ChaCha20 Poly1305 密码套件。(由 Christian Heimes 在 bpo-27850bpo-27766 中贡献。)

SSLContext 具有更好的选项和密码默认配置。(由 Christian Heimes 在 bpo-28043 中贡献。)

可以使用新的 SSLSession 类将 SSL 会话从一个客户端连接复制到另一个客户端连接。TLS 会话恢复可以加速初始握手,减少延迟并提高性能(由 Christian Heimes 在 bpo-19500 中基于 Alex Warhawk 的草案贡献。)

可以使用新的 get_ciphers() 方法按密码优先级顺序获取已启用密码的列表。

所有常量和标志都已转换为 IntEnumIntFlags。(由 Christian Heimes 在 bpo-28025 中贡献。)

SSLContext 添加了服务器端和客户端特定的 TLS 协议。(由 Christian Heimes 在 bpo-28085 中贡献。)

添加了 ssl.SSLContext.post_handshake_auth 以启用,以及 ssl.SSLSocket.verify_client_post_handshake() 以启动 TLS 1.3 后握手身份验证。(由 Christian Heimes 在 gh-78851 中贡献。)

statistics

添加了新的 harmonic_mean() 函数。(由 Steven D’Aprano 在 bpo-27181 中贡献。)

struct

struct 现在通过 'e' 格式说明符支持 IEEE 754 半精度浮点数。(由 Eli Stevens、Mark Dickinson 在 bpo-11734 中贡献。)

subprocess

如果子进程仍在运行,则 subprocess.Popen 的析构函数现在会发出 ResourceWarning 警告。请使用上下文管理器协议(with proc: ...)或显式调用 wait() 方法来读取子进程的退出状态。(由 Victor Stinner 在 bpo-26741 中贡献。)

subprocess.Popen 构造函数和所有通过它传递参数的函数现在接受 encodingerrors 参数。指定其中任何一个都会为 stdinstdoutstderr 流启用文本模式。(由 Steve Dower 在 bpo-6135 中贡献。)

sys

新的 getfilesystemencodeerrors() 函数返回用于在 Unicode 文件名和字节文件名之间转换的错误模式的名称。(由 Steve Dower 在 bpo-27781 中贡献。)

在 Windows 上,getwindowsversion() 函数的返回值现在包含 platform_version 字段,该字段包含当前操作系统的准确主版本号、次版本号和内部版本号,而不是为该进程模拟的版本(由 Steve Dower 在 bpo-27932 中贡献。)

telnetlib

telnetlib.Telnet 现在是一个上下文管理器(由 Stéphane Wirtel 在 bpo-25485 中贡献)。

time

现在在所有平台上都可以使用 struct_time 属性 tm_gmtofftm_zone

timeit

添加了新的 Timer.autorange() 便利方法,用于重复调用 Timer.timeit(),以便总运行时间大于或等于 200 毫秒。(由 Steven D’Aprano 在 bpo-6422 中贡献。)

当最佳时间和最差时间之间存在较大(4 倍)差异时,timeit 现在会发出警告。(由 Serhiy Storchaka 在 bpo-23552 中贡献。)

tkinter

tkinter.Variable 类中添加了方法 trace_add()trace_remove()trace_info()。它们取代了使用过时的 Tcl 命令的旧方法 trace_variable()trace()trace_vdelete()trace_vinfo(),这些方法在未来版本的 Tcl 中可能无法正常工作。(由 Serhiy Storchaka 在 bpo-22115 中贡献。)

traceback

回溯模块和解释器的内置异常显示现在都会缩短回溯中重复行的长序列,如下例所示

>>> def f(): f()
...
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in f
  File "<stdin>", line 1, in f
  File "<stdin>", line 1, in f
  [Previous line repeated 995 more times]
RecursionError: maximum recursion depth exceeded

(由 Emanuel Barry 在 bpo-26823 中贡献。)

tracemalloc

tracemalloc 模块现在支持跟踪多个不同地址空间中的内存分配。

新增了 DomainFilter 过滤器类,用于按地址空间(域)过滤块跟踪。

(由 Victor Stinner 在 bpo-26588 中贡献。)

typing

由于 typing 模块是临时的,因此 Python 3.6 中引入的所有更改也都向后移植到了 Python 3.5.x。

typing 模块对泛型类型别名的支持得到了极大改进。例如,Dict[str, Tuple[S, T]] 现在是一个有效的类型注解。(由 Guido van Rossum 在 Github #195 中贡献。)

添加了 typing.ContextManager 类,用于表示 contextlib.AbstractContextManager。(由 Brett Cannon 在 bpo-25609 中贡献。)

添加了 typing.Collection 类,用于表示 collections.abc.Collection。(由 Ivan Levkivskyi 在 bpo-27598 中贡献。)

添加了 typing.ClassVar 类型构造,用于标记类变量。如 PEP 526 中介绍的那样,用 ClassVar 包裹的变量注解表明给定属性旨在用作类变量,并且不应在类的实例上设置。(由 Ivan Levkivskyi 在 Github #280 中贡献。)

新增了一个 TYPE_CHECKING 常量,静态类型检查器假定该常量为 True,但在运行时为 False。(由 Guido van Rossum 在 Github #230 中贡献。)

新增了 NewType() 辅助函数,用于为注解创建轻量级、独特的类型

from typing import NewType

UserId = NewType('UserId', int)
some_id = UserId(524313)

静态类型检查器会将新类型视为原始类型的子类。(由 Ivan Levkivskyi 在 Github #189 中贡献。)

unicodedata

unicodedata 模块现在使用来自 Unicode 9.0.0 的数据。(由 Benjamin Peterson 贡献。)

unittest.mock

Mock 类有以下改进

urllib.request

如果 HTTP 请求具有文件或可迭代的 body(而不是字节对象),但没有 Content-Length 标头,则 AbstractHTTPHandler 现在会回退使用分块传输编码,而不是抛出错误。(由 Demian Brecht 和 Rolf Krahl 在 bpo-12319 中贡献。)

urllib.robotparser

RobotFileParser 现在支持 Crawl-delayRequest-rate 扩展。(由 Nikolay Bogoychev 在 bpo-16099 中贡献。)

venv

venv 接受一个新参数 --prompt。此参数为虚拟环境提供了一个备选前缀。(由 Łukasz Balcerzak 提出,并由 Stéphane Wirtel 移植到 3.6,见 bpo-22829。)

warnings

warnings.warn_explicit() 函数添加了一个新的可选 source 参数:发出 ResourceWarning 的已销毁对象。还向 warnings.WarningMessage 添加了一个 source 属性(由 Victor Stinner 在 bpo-26568bpo-26567 中贡献)。

当记录 ResourceWarning 警告时,现在使用 tracemalloc 模块尝试检索已销毁对象的分配位置的回溯。

使用脚本 example.py 的示例

import warnings

def func():
    return open(__file__)

f = func()
f = None

命令 python3.6 -Wd -X tracemalloc=5 example.py 的输出

example.py:7: ResourceWarning: unclosed file <_io.TextIOWrapper name='example.py' mode='r' encoding='UTF-8'>
  f = None
Object allocated at (most recent call first):
  File "example.py", lineno 4
    return open(__file__)
  File "example.py", lineno 6
    f = func()

“Object allocated at” 回溯是新的,仅当 tracemalloc 正在跟踪 Python 内存分配,并且已导入 warnings 模块时才会显示。

winreg

添加了 64 位整数类型 REG_QWORD。(由 Clement Rouault 在 bpo-23026 中贡献。)

winsound

允许将关键字参数传递给 BeepMessageBeepPlaySound (bpo-27982)。

xmlrpc.client

xmlrpc.client 模块现在支持解组 Apache XML-RPC 实现用于数值和 None 的其他数据类型。(由 Serhiy Storchaka 在 bpo-26885 中贡献。)

zipfile

新的 ZipInfo.from_file() 类方法允许从文件系统文件创建 ZipInfo 实例。新的 ZipInfo.is_dir() 方法可用于检查 ZipInfo 实例是否表示目录。(由 Thomas Kluyver 在 bpo-26039 中贡献。)

现在,ZipFile.open() 方法既可以用来将数据写入 ZIP 文件,也可以用来提取数据。(由 Thomas Kluyver 在 bpo-26039 中贡献。)

zlib

现在,compress()decompress() 函数接受关键字参数。(由 Aviv Palivoda 在 bpo-26243 中贡献,以及 Xiang Zhang 在 bpo-16764 中贡献。)

优化

  • Python 解释器现在使用 16 位字码而不是字节码,这使得许多操作码优化成为可能。(由 Demur Rumed 贡献,并由 Serhiy Storchaka 和 Victor Stinner 提供输入和审查,分别在 bpo-26647bpo-28050 中。)

  • 现在,asyncio.Future 类有一个优化的 C 实现。(由 Yury Selivanov 和 INADA Naoki 在 bpo-26081 中贡献。)

  • 现在,asyncio.Task 类有一个优化的 C 实现。(由 Yury Selivanov 在 bpo-28544 中贡献。)

  • typing 模块中的各种实现改进(例如泛型类型的缓存)允许性能提高高达 30 倍,并减少内存占用。

  • 对于错误处理程序 surrogateescapeignorereplace,ASCII 解码器现在的速度提高了 60 倍(由 Victor Stinner 在 bpo-24870 中贡献)。

  • 对于错误处理程序 surrogateescape,ASCII 和 Latin1 编码器现在的速度提高了 3 倍(由 Victor Stinner 在 bpo-25227 中贡献)。

  • 对于错误处理程序 ignorereplacesurrogateescapesurrogatepass,UTF-8 编码器现在的速度提高了 75 倍(由 Victor Stinner 在 bpo-25267 中贡献)。

  • 对于错误处理程序 ignorereplacesurrogateescape,UTF-8 解码器现在的速度提高了 15 倍(由 Victor Stinner 在 bpo-25301 中贡献)。

  • bytes % args 现在速度提高了 2 倍。(由 Victor Stinner 在 bpo-25349 中贡献)。

  • bytearray % args 现在速度提高了 2.5 到 5 倍。(由 Victor Stinner 在 bpo-25399 中贡献)。

  • 优化了 bytes.fromhex()bytearray.fromhex():它们现在的速度提高了 2 倍到 3.5 倍。(由 Victor Stinner 在 bpo-25401 中贡献)。

  • 优化了 bytes.replace(b'', b'.')bytearray.replace(b'', b'.'):速度提高了 80%。(由 Josh Snider 在 bpo-26574 中贡献)。

  • PyMem_Malloc() 域 (PYMEM_DOMAIN_MEM) 的分配器函数现在使用 pymalloc 内存分配器,而不是 C 库的 malloc() 函数。 pymalloc 分配器针对小于或等于 512 字节且生命周期短的对象进行了优化,并对较大的内存块使用 malloc()。(由 Victor Stinner 在 bpo-26249 中贡献)。

  • 当反序列化许多小对象时,pickle.load()pickle.loads() 现在速度提高了 10%(由 Victor Stinner 在 bpo-27056 中贡献)。

  • 与传递位置参数相比,向函数传递关键字参数会产生开销。现在,在使用 Argument Clinic 实现的扩展函数中,此开销已大大减少。(由 Serhiy Storchaka 在 bpo-27574 中贡献)。

  • 优化了 glob()iglob() 函数,它们现在速度提高了大约 3-6 倍。(由 Serhiy Storchaka 在 bpo-25596 中贡献)。

  • 通过使用 os.scandir(),优化了 pathlib 中的 globbing;现在速度提高了大约 1.5-4 倍。(由 Serhiy Storchaka 在 bpo-26032 中贡献)。

  • xml.etree.ElementTree 的解析、迭代和深拷贝性能得到了显著提高。(由 Serhiy Storchaka 在 bpo-25638bpo-25873bpo-25869 中贡献。)

  • 从浮点数和小数创建 fractions.Fraction 实例现在速度提高了 2 到 3 倍。(由 Serhiy Storchaka 在 bpo-25971 中贡献)。

构建和 C API 更改

其他改进

  • --version (短形式: -V) 被提供两次时,Python 会打印 sys.version 以获取详细信息。

    $ ./python -VV
    Python 3.6.0b4+ (3.6:223967b49e49+, Nov 21 2016, 20:55:04)
    [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)]
    

已弃用

新关键字

asyncawait 不建议用作变量、类、函数或模块名。由 PEP 492 在 Python 3.5 中引入,它们将在 Python 3.7 中成为正式关键字。从 Python 3.6 开始,使用 asyncawait 作为名称将生成 DeprecationWarning

已弃用的 Python 行为

在生成器内部引发 StopIteration 异常现在将生成 DeprecationWarning,并且在 Python 3.7 中将触发 RuntimeError。 有关详细信息,请参阅 PEP 479: 更改生成器内部的 StopIteration 处理

现在期望 __aiter__() 方法直接返回异步迭代器,而不是像以前那样返回可等待对象。执行前者将触发 DeprecationWarning。向后兼容性将在 Python 3.7 中删除。(由 Yury Selivanov 在 bpo-27243 中贡献。)

现在,不是有效转义序列的反斜杠字符对会生成 DeprecationWarning。虽然这最终会变成 SyntaxError,但这不会在几个 Python 版本中实现。(由 Emanuel Barry 在 bpo-27364 中贡献。)

在执行相对导入时,当 __spec____package__ 未定义时,回退到调用模块的 __name____path__ 现在会引发 ImportWarning。(由 Rose Ames 在 bpo-25791 中贡献。)

已弃用的 Python 模块、函数和方法

asynchat

asynchat 已弃用,推荐使用 asyncio。(由 Mariatta 在 bpo-25002 中贡献。)

asyncore

asyncore 已弃用,推荐使用 asyncio。(由 Mariatta 在 bpo-25002 中贡献。)

dbm

与其他 dbm 实现不同,dbm.dumb 模块使用 'rw' 模式创建数据库,并允许修改以 'r' 模式打开的数据库。此行为现在已弃用,并将在 3.8 中删除。(由 Serhiy Storchaka 在 bpo-21708 中贡献。)

distutils

distutils.Distribution 构造函数的未文档化参数 extra_path 现在被视为已弃用,如果设置了该参数,则会引发警告。对该参数的支持将在未来的 Python 版本中删除。有关详细信息,请参阅 bpo-27919

grp

已弃用 getgrgid() 中对非整数参数的支持。(由 Serhiy Storchaka 在 bpo-26129 中贡献。)

importlib

importlib.machinery.SourceFileLoader.load_module()importlib.machinery.SourcelessFileLoader.load_module() 方法现在已弃用。它们是 importlib.abc.Loader.load_module()importlib 中唯一剩余的实现,而在以前的 Python 版本中,这些实现尚未弃用,而是推荐使用 importlib.abc.Loader.exec_module()

importlib.machinery.WindowsRegistryFinder 类现在已弃用。从 3.6.0 开始,它仍然默认添加到 sys.meta_path (在 Windows 上),但这可能会在未来的版本中更改。

os

现在已弃用 os 函数,compile() 和类似函数中对作为路径的通用 类字节对象 的未文档化支持。(由 Serhiy Storchaka 在 bpo-25791bpo-26754 中贡献。)

re

已弃用对正则表达式中间内联标志 (?letters) 的支持,并将在未来的 Python 版本中删除。仍然允许在正则表达式开头使用标志。(由 Serhiy Storchaka 在 bpo-22493 中贡献。)

ssl

OpenSSL 0.9.8、1.0.0 和 1.0.1 已弃用且不再受支持。未来,ssl 模块将至少需要 OpenSSL 1.0.2 或 1.1.0。

诸如 certfilekeyfilecheck_hostname 等与 SSL 相关的参数,在 ftplibhttp.clientimaplibpoplibsmtplib 中已被弃用,建议改用 context。(由 Christian Heimes 在 bpo-28022 中贡献。)

ssl 模块的几个协议和函数现在已弃用。某些功能在未来的 OpenSSL 版本中将不再可用。其他功能已被弃用,建议改用不同的 API。(由 Christian Heimes 在 bpo-28022bpo-26470 中贡献。)

tkinter

现在已弃用 tkinter.tix 模块。tkinter 用户应改用 tkinter.ttk

venv

已弃用 pyvenv 脚本,建议使用 python3 -m venv。这可以避免 pyvenv 连接到哪个 Python 解释器的混淆,从而避免虚拟环境使用哪个 Python 解释器的混淆。(由 Brett Cannon 在 bpo-25154 中贡献。)

xml

  • 作为对 DTD 和外部实体检索的缓解措施,xml.dom.minidomxml.sax 模块默认不再处理外部实体。(由 Christian Heimes 在 gh-61441 中贡献。)

已弃用的 C API 函数和类型

未记录的函数 PyUnicode_AsEncodedObject()PyUnicode_AsDecodedObject()PyUnicode_AsEncodedUnicode()PyUnicode_AsDecodedUnicode() 现在已弃用。请改用 基于通用编解码器的 API

已弃用的构建选项

在非 macOS UNIX 平台上,--with-system-ffi 配置标志现在默认启用。可以使用 --without-system-ffi 禁用它,但使用该标志已被弃用,并且在 Python 3.7 中将不被接受。macOS 不受此更改的影响。请注意,许多操作系统发行商在构建其系统 Python 时已经使用了 --with-system-ffi 标志。

已移除

API 和功能移除

  • 在正则表达式中,由 '\' 和一个 ASCII 字母组成的未知转义符现在将导致错误。在 re.sub() 的替换模板中,仍然允许使用它们,但已弃用。re.LOCALE 标志现在只能与二进制模式一起使用。

  • 删除了 inspect.getmoduleinfo()(自 CPython 3.3 起已弃用)。应该使用 inspect.getmodulename() 获取给定路径的模块名称。(由 Yury Selivanov 在 bpo-13248 中贡献。)

  • traceback 模块中删除了 traceback.Ignore 类和 traceback.usagetraceback.modnametraceback.fullmodnametraceback.find_lines_from_codetraceback.find_linestraceback.find_stringstraceback.find_executable_lines 方法。它们是自 Python 3.2 起已弃用的未记录方法,并且可以从私有方法获得等效功能。

  • 删除了 tkinter 窗口小部件类中的 tk_menuBar()tk_bindForTraversal() 虚拟方法(相应的 Tk 命令自 Tk 4.0 起已过时)。

  • zipfile.ZipFile 类的 open() 方法不再支持 'U' 模式(自 Python 3.4 起已弃用)。请使用 io.TextIOWrapper通用换行符 模式读取压缩的文本文件。

  • 删除了未记录的 INCDROMDLFCNTYPESCDIOSTROPTS 模块。它们曾存在于特定于平台的 Lib/plat-*/ 目录中,但长期过时、在不同平台上的可用性不一致且未维护。创建这些模块的脚本仍然可以在源代码发行版的 Tools/scripts/h2py.py 中找到。

  • 删除了已弃用的 asynchat.fifo 类。

移植到 Python 3.6

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

“python”命令行为的更改

  • 现在默认关闭使用定义的 COUNT_ALLOCSSHOW_ALLOC_COUNTSHOW_TRACK_COUNT 宏的特殊 Python 构建的输出。可以使用 -X showalloccount 选项重新启用它。现在输出到 stderr 而不是 stdout。(由 Serhiy Storchaka 在 bpo-23034 中贡献。)

Python API 的更改

  • open() 将不再允许将 'U' 模式标志与 '+' 组合使用。(由 Jeff Balogh 和 John O’Connor 在 bpo-2091 中贡献。)

  • sqlite3 在执行 DDL 语句之前,不再隐式提交打开的事务。

  • 在 Linux 上,os.urandom() 现在会阻塞,直到系统 urandom 熵池初始化完毕,以提高安全性。

  • 当定义了 importlib.abc.Loader.exec_module() 时,也必须定义 importlib.abc.Loader.create_module()

  • msg 参数未设置时,PyErr_SetImportError() 现在会设置 TypeError。之前只返回 NULL

  • 代码对象的 co_lnotab 属性的格式已更改,以支持负行号增量。默认情况下,Python 不会发出带有负行号增量的字节码。使用 frame.f_linenoPyFrame_GetLineNumber()PyCode_Addr2Line() 的函数不受影响。直接解码 co_lnotab 的函数应更新为对行号增量使用有符号的 8 位整数类型,但这仅在支持使用负行号增量的应用程序时才是必需的。请参阅 Objects/lnotab_notes.txt 获取 co_lnotab 的格式以及如何解码它,并参阅 PEP 511 了解其基本原理。

  • compileall 模块中的函数现在返回布尔值而不是 10 来表示成功或失败。由于布尔值是整数的子类,因此如果您执行 10 的身份检查,这才会成为问题。请参阅 bpo-25768

  • 读取 urllib.parse.urlsplit()urlparse()port 属性现在会为超出范围的值引发 ValueError,而不是返回 None。请参阅 bpo-20059

  • imp 模块现在引发 DeprecationWarning 而不是 PendingDeprecationWarning

  • 以下模块已在其 __all__ 属性中添加了缺少的 API,以匹配文档化的 API:calendar, cgi, csv, ElementTree, enum, fileinput, ftplib, logging, mailbox, mimetypes, optparse, plistlib, smtpd, subprocess, tarfile, threadingwave。这意味着当使用 import * 时,它们将导出新的符号。(由 Joel Taddei 和 Jacek Kołodziej 在 bpo-23883 中贡献。)

  • 当执行相对导入时,如果 __package____spec__.parent 不相等,则会引发 ImportWarning。(由 Brett Cannon 在 bpo-25791 中贡献。)

  • 当执行相对导入且没有已知父包时,将引发 ImportError。以前,可能会引发 SystemError。(由 Brett Cannon 在 bpo-18018 中贡献。)

  • 基于 socketserver 模块的服务器,包括在 http.serverxmlrpc.serverwsgiref.simple_server 中定义的服务器,现在只捕获派生自 Exception 的异常。 因此,如果请求处理程序引发诸如 SystemExitKeyboardInterrupt 的异常,则不再调用 handle_error(),并且该异常将停止单线程服务器。(由 Martin Panter 在 bpo-23430 中贡献。)

  • spwd.getspnam() 现在如果用户没有权限,则会引发 PermissionError,而不是 KeyError

  • 如果底层系统调用报告错误(例如 EBADF),则 socket.socket.close() 方法现在会引发异常。(由 Martin Panter 在 bpo-26685 中贡献。)

  • smtpd.SMTPChannelsmtpd.SMTPServer 构造函数的 decode_data 参数现在默认为 False。 这意味着传递给 process_message() 的参数现在默认为字节对象,并且将向 process_message() 传递关键字参数。 已经根据 3.5 生成的弃用警告更新的代码不会受到影响。

  • dump()dumps()load()loads() 函数以及 JSONEncoderJSONDecoder 类构造函数在 json 模块中的所有可选参数现在都是仅限关键字的。(由 Serhiy Storchaka 在 bpo-18726 中贡献。)

  • 不覆盖 type.__new__type 的子类可能不再使用单参数形式来获取对象的类型。

  • 作为 PEP 487 的一部分,传递给 type (除了元类提示 metaclass 之外)的关键字参数的处理现在一致地委托给 object.__init_subclass__()。 这意味着 type.__new__()type.__init__() 现在都接受任意关键字参数,但 object.__init_subclass__()(从 type.__new__() 调用)默认情况下会拒绝它们。 接受其他关键字参数的自定义元类将需要相应地调整它们对 type.__new__() 的调用(无论是直接调用还是通过 super 调用)。

  • distutils.command.sdist.sdist 中,default_format 属性已被删除,不再被使用。 相反,gzipped tarfile 格式是所有平台上的默认格式,并且不会进行特定于平台的选择。 在 Windows 上构建发行版并且需要 zip 发行版的环境中,请使用包含以下内容的 setup.cfg 文件配置项目

    [sdist]
    formats=zip
    

    此行为也已通过 Setuptools 26.0.0 反向移植到较早的 Python 版本。

  • urllib.request 模块和 http.client.HTTPConnection.request() 方法中,如果没有指定 Content-Length 标头字段,并且请求正文是文件对象,则现在使用 HTTP 1.1 分块编码发送。 如果必须将文件对象发送到 HTTP 1.0 服务器,则现在必须由调用方指定 Content-Length 值。(由 Demian Brecht 和 Rolf Krahl 贡献,Martin Panter 进行了调整,参见 bpo-12319。)

  • DictReader 现在返回 OrderedDict 类型的行。(由 Steve Holden 在 bpo-27842 中贡献。)

  • 如果平台不支持,则不再将 crypt.METHOD_CRYPT 添加到 crypt.methods 中。(由 Victor Stinner 在 bpo-25287 中贡献。)

  • namedtuple() 的 *verbose* 和 *rename* 参数现在是仅关键字参数。(由 Raymond Hettinger 在 bpo-25628 中贡献。)

  • 在 Linux 上,ctypes.util.find_library() 现在在 LD_LIBRARY_PATH 中查找共享库。(由 Vinay Sajip 在 bpo-9998 中贡献。)

  • imaplib.IMAP4 类现在处理从服务器发送的消息中包含 ']' 字符的标志,以提高实际兼容性。(由 Lita Cho 在 bpo-21815 中贡献。)

  • mmap.write() 函数现在像其他写入方法一样返回写入的字节数。(由 Jakub Stasiak 在 bpo-26335 中贡献。)

  • pkgutil.iter_modules()pkgutil.walk_packages() 函数现在返回 ModuleInfo 命名元组。(由 Ramchandra Apte 在 bpo-17211 中贡献。)

  • re.sub() 现在即使在字符串中未找到模式,也会为替换模板中的无效数字组引用引发错误。 无效组引用的错误消息现在包括组索引和引用的位置。(由 SilentGhost,Serhiy Storchaka 在 bpo-25953 中贡献。)

  • zipfile.ZipFile 现在对于无法识别的压缩值会引发 NotImplementedError 异常。 之前会引发普通的 RuntimeError 异常。 此外,在已关闭的 ZipFile 上调用 ZipFile 方法,或在以模式 'r' 创建的 ZipFile 上调用 write() 方法时,会引发 ValueError 异常。 之前在这些情况下会引发 RuntimeError 异常。

  • 当自定义元类与无参数的 super() 或从方法到隐式的 __class__ 闭包变量的直接引用结合使用时,隐式的 __classcell__ 命名空间条目现在必须传递给 type.__new__ 进行初始化。 如果不这样做,在 Python 3.6 中将导致 DeprecationWarning,而在 Python 3.8 中将导致 RuntimeError

  • 随着 ModuleNotFoundError 的引入,导入系统使用者可能会开始期望导入系统替换在适当的时候引发更具体的异常,而不是不太具体的 ImportError。 为了与此类使用者提供未来的兼容性,完全替换 __import__() 的替代导入系统的实现者需要更新其实现,以便在根本找不到模块时引发新的子类。 默认导入系统的兼容插件的实现者不需要进行任何更改,因为默认导入系统会在适当的时候引发新的子类。

C API 中的更改

  • PyMem_Malloc() 分配器系列现在使用 pymalloc 分配器,而不是系统 malloc()。 在没有持有 GIL 的情况下调用 PyMem_Malloc() 的应用程序现在可能会崩溃。 将 PYTHONMALLOC 环境变量设置为 debug 以验证应用程序中内存分配器的使用情况。 请参阅 bpo-26249

  • 如果刷新缓冲数据失败,Py_Exit() (和主解释器) 现在会将退出状态覆盖为 120。请参阅 bpo-5319

CPython 字节码更改

Python 3.6 中的 字节码 发生了一些重大更改。

  • Python 解释器现在使用 16 位字码而不是字节码。(由 Demur Rumed 贡献,并由 Serhiy Storchaka 和 Victor Stinner 在 bpo-26647bpo-28050 中提供输入和审查。)

  • 作为 格式化字符串字面量 实现的一部分,新的 FORMAT_VALUEBUILD_STRING 操作码。(由 Eric Smith 在 bpo-25483 中贡献,Serhiy Storchaka 在 bpo-27078 中贡献。)

  • 新的 BUILD_CONST_KEY_MAP 操作码用于优化具有常量键的字典的创建。(由 Serhiy Storchaka 在 bpo-27140 中贡献。)

  • 为了获得更好的性能和更简单的实现,函数调用操作码已经过大量修改。MAKE_FUNCTION, CALL_FUNCTION, CALL_FUNCTION_KWBUILD_MAP_UNPACK_WITH_CALL 操作码已修改,添加了新的 CALL_FUNCTION_EXBUILD_TUPLE_UNPACK_WITH_CALL,并移除了 CALL_FUNCTION_VARCALL_FUNCTION_VAR_KWMAKE_CLOSURE 操作码。(由 Demur Rumed 在 bpo-27095 中贡献,Serhiy Storchaka 在 bpo-27213, bpo-28257 中贡献。)

  • 为了支持新的 变量注解 语法,添加了新的 SETUP_ANNOTATIONSSTORE_ANNOTATION 操作码。(由 Ivan Levkivskyi 在 bpo-27985 中贡献。)

Python 3.6.2 中的显著变化

新的 make regen-all 构建目标

为了简化交叉编译,并确保 CPython 可以在无需现有可用 Python 版本的情况下可靠地编译,基于 autotools 的构建系统不再尝试基于文件修改时间隐式地重新编译生成的文件。

相反,添加了一个新的 make regen-all 命令,以便在需要时强制重新生成这些文件(例如,在基于预生成的版本已经构建了 Python 的初始版本之后)。

还定义了更多有选择性的重新生成目标 - 有关详细信息,请参阅 Makefile.pre.in

(由 Victor Stinner 在 bpo-23404 中贡献。)

在 3.6.2 版本中添加。

删除 make touch 构建目标

之前用于通过更新修改时间来请求隐式重新生成生成文件的 make touch 构建目标已被删除。

它已被新的 make regen-all 目标所取代。

(由 Victor Stinner 在 bpo-23404 中贡献。)

在 3.6.2 版本中更改。

Python 3.6.4 中的显著变化

作为公共 API 一部分的 PyExc_RecursionErrorInst 单例已被删除,因为其成员从不清空可能会导致解释器最终确定期间出现段错误。(由 Xavier de Gaye 在 bpo-22898bpo-30697 中贡献。)

Python 3.6.5 中的显著变化

现在,locale.localeconv() 函数在某些情况下会临时将 LC_CTYPE 区域设置设置为 LC_NUMERIC 区域设置。(由 Victor Stinner 在 bpo-31900 中贡献。)

Python 3.6.7 中的显著变化

xml.dom.minidomxml.sax 模块默认不再处理外部实体。另请参阅 gh-61441

在 3.6.7 中,tokenize 模块现在会在输入不包含尾随换行符时隐式发出 NEWLINE 标记。此行为现在与 C 标记器在内部执行的操作相匹配。(由 Ammar Askar 在 bpo-33899 中贡献。)

Python 3.6.10 中的显著变化

由于重大的安全问题,不再支持 asyncio.loop.create_datagram_endpoint()reuse_address 参数。这是由于 UDP 中套接字选项 SO_REUSEADDR 的行为。有关更多详细信息,请参阅 loop.create_datagram_endpoint() 的文档。(由 Kyle Stanley、Antoine Pitrou 和 Yury Selivanov 在 bpo-37228 中贡献。)

Python 3.6.13 中的显著变化

早期版本的 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.6.14 中的显著变化

一个安全修复程序更改了 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