Python 3.5 中的新特性

编辑:

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

本文解释了 Python 3.5 相较于 3.4 的新特性。Python 3.5 于 2015 年 9 月 13 日发布。有关所有更改的完整列表,请参阅更新日志

参见

PEP 478 - Python 3.5 发布时间表

摘要 – 发布亮点

新语法功能

  • PEP 492,带有 async 和 await 语法的协程。

  • PEP 465,一个新的矩阵乘法运算符:a @ b

  • PEP 448,额外的解包泛化。

新库模块

新的内置功能

  • bytes % argsbytearray % argsPEP 461 – 为 bytes 和 bytearray 添加 % 格式化。

  • 新的 bytes.hex()bytearray.hex()memoryview.hex() 方法。(由 Arnon Yaari 在 bpo-9951 中贡献。)

  • memoryview 现在支持元组索引(包括多维)。(由 Antoine Pitrou 在 bpo-23632 中贡献。)

  • 生成器新增 gi_yieldfrom 属性,它返回正在被 yield from 表达式迭代的对象。(由 Benno Leslie 和 Yury Selivanov 在 bpo-24450 中贡献。)

  • 当达到最大递归深度时,现在会引发新的 RecursionError 异常。(由 Georg Brandl 在 bpo-19235 中贡献。)

CPython 实现改进

  • LC_TYPE 区域设置为 POSIX 区域设置(C 区域设置)时,sys.stdinsys.stdout 现在使用 surrogateescape 错误处理程序,而不是 strict 错误处理程序。(由 Victor Stinner 在 bpo-19977 中贡献。)

  • .pyo 文件不再使用,已被一种更灵活的方案取代,该方案在 .pyc 名称中明确包含优化级别。(参见PEP 488 概述。)

  • 内置模块和扩展模块现在采用多阶段过程进行初始化,这类似于 Python 模块的加载方式。(参见PEP 489 概述。)

标准库的重大改进

安全改进

  • SSLv3 现在在整个标准库中禁用。它仍然可以通过手动实例化 ssl.SSLContext 来启用。(有关更多详细信息,请参阅 bpo-22638;此更改已反向移植到 CPython 3.4 和 2.7。)

  • HTTP cookie 解析现在更严格,以防止潜在的注入攻击。(由 Antoine Pitrou 在 bpo-22796 中贡献。)

Windows 改进

  • 新的 Windows 安装程序取代了旧的 MSI。有关更多信息,请参阅在 Windows 上使用 Python

  • Windows 构建现在使用 Microsoft Visual C++ 14.0,扩展模块也应使用相同的版本。

请继续阅读,了解用户面临的更改的全面列表,包括许多其他较小的改进、CPython 优化、弃用和潜在的移植问题。

新功能

PEP 492 - 带有 async 和 await 语法的协程

PEP 492 通过添加可等待对象协程函数异步迭代异步上下文管理器,极大地改进了 Python 中对异步编程的支持。

协程函数使用新的 async def 语法声明

>>> async def coro():
...     return 'spam'

在协程函数内部,新的 await 表达式可用于暂停协程执行,直到结果可用。任何对象都可以被 await,只要它通过定义 __await__() 方法实现了可等待协议。

PEP 492 还添加了 async for 语句,以便方便地迭代异步可迭代对象。

使用新语法编写的简陋 HTTP 客户端示例

import asyncio

async def http_get(domain):
    reader, writer = await asyncio.open_connection(domain, 80)

    writer.write(b'\r\n'.join([
        b'GET / HTTP/1.1',
        b'Host: %b' % domain.encode('latin-1'),
        b'Connection: close',
        b'', b''
    ]))

    async for line in reader:
        print('>>>', line)

    writer.close()

loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(http_get('example.com'))
finally:
    loop.close()

与异步迭代类似,异步上下文管理器也有新的语法。以下脚本

import asyncio

async def coro(name, lock):
    print('coro {}: waiting for lock'.format(name))
    async with lock:
        print('coro {}: holding the lock'.format(name))
        await asyncio.sleep(1)
        print('coro {}: releasing the lock'.format(name))

loop = asyncio.get_event_loop()
lock = asyncio.Lock()
coros = asyncio.gather(coro(1, lock), coro(2, lock))
try:
    loop.run_until_complete(coros)
finally:
    loop.close()

将输出

coro 2: waiting for lock
coro 2: holding the lock
coro 1: waiting for lock
coro 2: releasing the lock
coro 1: holding the lock
coro 1: releasing the lock

请注意,async forasync with 都只能在用 async def 声明的协程函数内部使用。

协程函数旨在在兼容的事件循环中运行,例如 asyncio 循环

备注

3.5.2 版中已更改: 从 CPython 3.5.2 开始,__aiter__ 可以直接返回异步迭代器。返回可等待对象将导致 PendingDeprecationWarning

有关更多详细信息,请参阅异步迭代器文档部分。

参见

PEP 492 – 带有 async 和 await 语法的协程

PEP 由 Yury Selivanov 编写并实现。

PEP 465 - 矩阵乘法的专用中缀运算符

PEP 465 添加了用于矩阵乘法的 @ 中缀运算符。目前,没有内置的 Python 类型实现这个新运算符,但是,可以通过为常规、反射和原地矩阵乘法定义 __matmul__()__rmatmul__()__imatmul__() 来实现它。这些方法的语义类似于定义其他中缀算术运算符的方法。

矩阵乘法在数学、科学、工程等许多领域是一种非常常见的运算,添加 @ 可以编写更简洁的代码

S = (H @ beta - r).T @ inv(H @ V @ H.T) @ (H @ beta - r)

而不是

S = dot((dot(H, beta) - r).T,
        dot(inv(dot(dot(H, V), H.T)), dot(H, beta) - r))

NumPy 1.10 支持新运算符

>>> import numpy

>>> x = numpy.ones(3)
>>> x
array([ 1., 1., 1.])

>>> m = numpy.eye(3)
>>> m
array([[ 1., 0., 0.],
       [ 0., 1., 0.],
       [ 0., 0., 1.]])

>>> x @ m
array([ 1., 1., 1.])

参见

PEP 465 – 矩阵乘法的专用中缀运算符

PEP 由 Nathaniel J. Smith 编写;由 Benjamin Peterson 实现。

PEP 448 - 额外的解包泛化

PEP 448 扩展了 * 可迭代解包运算符和 ** 字典解包运算符的允许用法。现在可以在函数调用中使用任意数量的解包

>>> print(*[1], *[2], 3, *[4, 5])
1 2 3 4 5

>>> def fn(a, b, c, d):
...     print(a, b, c, d)
...

>>> fn(**{'a': 1, 'c': 3}, **{'b': 2, 'd': 4})
1 2 3 4

类似地,元组、列表、集合和字典显示允许多次解包(参见表达式列表字典显示

>>> *range(4), 4
(0, 1, 2, 3, 4)

>>> [*range(4), 4]
[0, 1, 2, 3, 4]

>>> {*range(4), 4, *(5, 6, 7)}
{0, 1, 2, 3, 4, 5, 6, 7}

>>> {'x': 1, **{'y': 2}}
{'x': 1, 'y': 2}

参见

PEP 448 – 额外的解包泛化

PEP 由 Joshua Landau 编写;由 Neil Girdhar、Thomas Wouters 和 Joshua Landau 实现。

PEP 461 - bytes 和 bytearray 的百分号格式化支持

PEP 461bytesbytearray 添加了 % 插值运算符的支持。

虽然插值通常被认为是字符串操作,但在某些情况下,对 bytesbytearrays 进行插值是有意义的,而弥补此功能缺失所需的工作会降低代码的整体可读性。在处理线格式协议时,这个问题尤为重要,这些协议通常是二进制和 ASCII 兼容文本的混合。

示例:

>>> b'Hello %b!' % b'World'
b'Hello World!'

>>> b'x=%i y=%f' % (1, 2.5)
b'x=1 y=2.500000'

Unicode 不允许用于 %b,但它被 %a 接受(等同于 repr(obj).encode('ascii', 'backslashreplace')

>>> b'Hello %b!' % 'World'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: %b requires bytes, or an object that implements __bytes__, not 'str'

>>> b'price: %a' % '10€'
b"price: '10\\u20ac'"

请注意,%s%r 转换类型虽然受支持,但应仅用于需要与 Python 2 兼容的代码库。

参见

PEP 461 – 为 bytes 和 bytearray 添加 % 格式化

PEP 由 Ethan Furman 编写;由 Neil Schemenauer 和 Ethan Furman 实现。

PEP 484 - 类型提示

自 Python 3.0 版本以来(PEP 3107),函数注解语法一直是 Python 的一个特性,但注解的语义一直未定义。

经验表明,大多数函数注解的用途是为函数参数和返回值提供类型提示。很明显,如果标准库包含类型注解的基本定义和工具,将对 Python 用户有所裨益。

PEP 484 引入了一个临时模块来提供这些标准定义和工具,以及一些在注解不可用情况下的约定。

例如,这是一个简单的函数,其参数和返回类型在注解中声明

def greeting(name: str) -> str:
    return 'Hello ' + name

虽然这些注解在运行时通过通常的 __annotations__ 属性可用,但 运行时不会发生自动类型检查。相反,假设会使用一个单独的离线类型检查器(例如 mypy)进行按需源代码分析。

类型系统支持联合类型、泛型类型以及一个名为 Any 的特殊类型,该类型与所有类型一致(即可以赋值给所有类型,也可以从所有类型赋值)。

参见

  • typing 模块文档

  • PEP 484 – 类型提示

    PEP 由 Guido van Rossum、Jukka Lehtosalo 和 Łukasz Langa 编写;由 Guido van Rossum 实现。

  • PEP 483 – 类型提示的理论

    PEP 由 Guido van Rossum 编写

PEP 471 - os.scandir() 函数 – 更好更快的目录迭代器

PEP 471 向标准库添加了一个新的目录迭代函数 os.scandir()。此外,os.walk() 现在使用 scandir 实现,这使得它在 POSIX 系统上快 3 到 5 倍,在 Windows 系统上快 7 到 20 倍。这主要是通过大大减少遍历目录树所需的 os.stat() 调用次数来实现的。

此外,scandir 返回一个迭代器,而不是返回一个文件名列表,这在迭代非常大的目录时提高了内存效率。

以下示例展示了 os.scandir() 的简单用法,以显示给定 path 中不以 '.' 开头的所有文件(不包括目录)。entry.is_file() 调用通常不会产生额外的系统调用

for entry in os.scandir(path):
    if not entry.name.startswith('.') and entry.is_file():
        print(entry.name)

参见

PEP 471 – os.scandir() 函数 – 更好更快的目录迭代器

PEP 由 Ben Hoyt 在 Victor Stinner 的帮助下编写并实现。

PEP 475: 重试因 EINTR 失败的系统调用

当等待 I/O 的系统调用被信号中断时,会返回 errno.EINTR 错误代码。以前,在这种情况下,Python 会引发 InterruptedError。这意味着,在编写 Python 应用程序时,开发人员有两个选择

  1. 忽略 InterruptedError

  2. 处理 InterruptedError 并在每个调用点尝试重新启动被中断的系统调用。

第一个选项会导致应用程序间歇性失败。第二个选项增加了大量的样板代码,使代码几乎无法阅读。比较一下

print("Hello World")

while True:
    try:
        print("Hello World")
        break
    except InterruptedError:
        continue

PEP 475 实现了在 EINTR 情况下自动重试系统调用。这在大多数情况下消除了用户代码中处理 EINTRInterruptedError 的负担,并使 Python 程序(包括标准库)更加健壮。请注意,仅当信号处理程序不引发异常时,系统调用才会重试。

以下是现在在被信号中断时会重试的函数列表

参见

PEP 475 – 重试因 EINTR 失败的系统调用

PEP 和实现由 Charles-François Natali 和 Victor Stinner 编写,Antoine Pitrou(法国连接)协助。

PEP 479: 改变生成器内部 StopIteration 的处理方式

Python 3.4 及更早版本中生成器与 StopIteration 的交互有时令人惊讶,并可能隐藏难以发现的错误。以前,在生成器函数内部意外引发的 StopIteration 会被驱动生成器的循环构造解释为迭代结束。

PEP 479 改变了生成器的行为:当在生成器内部引发 StopIteration 异常时,在它退出生成器帧之前,它会被替换为 RuntimeError。此更改的主要目标是简化调试,解决当不带保护的 next() 调用引发 StopIteration 并导致由生成器控制的迭代静默终止的情况。这与 yield from 构造结合使用时尤其有害。

这是一个向后不兼容的更改,因此要启用新行为,需要进行 __future__ 导入

>>> from __future__ import generator_stop

>>> def gen():
...     next(iter([]))
...     yield
...
>>> next(gen())
Traceback (most recent call last):
  File "<stdin>", line 2, in gen
StopIteration

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: generator raised StopIteration

如果没有 __future__ 导入,当在生成器内部引发 StopIteration 异常时,将引发 PendingDeprecationWarning

参见

PEP 479 – 改变生成器内部 StopIteration 的处理方式

PEP 由 Chris Angelico 和 Guido van Rossum 编写。由 Chris Angelico、Yury Selivanov 和 Nick Coghlan 实现。

PEP 485: 用于测试近似相等性的函数

PEP 485 添加了 math.isclose()cmath.isclose() 函数,它们用于判断两个值是否近似相等或“接近”。两个值是否被认为是接近,由给定的绝对和相对容差决定。相对容差是 isclose 参数之间允许的最大差异,相对于较大的绝对值

>>> import math
>>> a = 5.0
>>> b = 4.99998
>>> math.isclose(a, b, rel_tol=1e-5)
True
>>> math.isclose(a, b, rel_tol=1e-6)
False

也可以使用绝对容差来比较两个值,它必须是非负值

>>> import math
>>> a = 5.0
>>> b = 4.99998
>>> math.isclose(a, b, abs_tol=0.00003)
True
>>> math.isclose(a, b, abs_tol=0.00001)
False

参见

PEP 485 – 用于测试近似相等性的函数

PEP 由 Christopher Barker 编写;由 Chris Barker 和 Tal Einat 实现。

PEP 486: 使 Python 启动器感知虚拟环境

PEP 486 使 Windows 启动器(参见PEP 397)能够感知活动的虚拟环境。当使用默认解释器且 VIRTUAL_ENV 环境变量已设置时,将使用虚拟环境中的解释器。

参见

PEP 486 – 使 Python 启动器感知虚拟环境

PEP 由 Paul Moore 编写并实现。

PEP 488: 移除 PYO 文件

PEP 488 废弃了 .pyo 文件的概念。这意味着 .pyc 文件既表示未优化字节码,也表示优化字节码。为了避免不断重新生成字节码文件,当字节码被优化时,.pyc 文件现在在其名称中包含一个可选的 opt- 标签。这带来的副作用是,在 -O-OO 下运行时,不再出现字节码文件名冲突。因此,由 -O-OO 生成的字节码文件现在可以同时存在。importlib.util.cache_from_source() 具有更新的 API 来帮助实现此更改。

参见

PEP 488 – 移除 PYO 文件

PEP 由 Brett Cannon 编写并实现。

PEP 489: 多阶段扩展模块初始化

PEP 489 更新了扩展模块初始化,以利用 Python 3.4 中 PEP 451 引入的两步模块加载机制。

此更改使选择使用新机制的扩展模块的导入语义更接近 Python 源模块和字节码模块的导入语义,包括能够使用任何有效的标识符作为模块名称,而不是仅限于 ASCII。

参见

PEP 489 – 多阶段扩展模块初始化

PEP 由 Petr Viktorin、Stefan Behnel 和 Nick Coghlan 编写;由 Petr Viktorin 实现。

其他语言更改

对核心 Python 语言做了一些较小的更改

  • 添加了 "namereplace" 错误处理程序。"backslashreplace" 错误处理程序现在支持解码和转换。(由 Serhiy Storchaka 在 bpo-19676bpo-22286 中贡献。)

  • -b 选项现在影响 bytesint 的比较。(由 Serhiy Storchaka 在 bpo-23681 中贡献。)

  • 新的哈萨克语 kz1048 和塔吉克语 koi8_t 编码解码器。(由 Serhiy Storchaka 在 bpo-22682bpo-22681 中贡献。)

  • 属性文档字符串现在可写。这对于 collections.namedtuple() 文档字符串尤其有用。(由 Berker Peksag 在 bpo-24064 中贡献。)

  • 现在支持涉及相对导入的循环导入。(由 Brett Cannon 和 Antoine Pitrou 在 bpo-17636 中贡献。)

新模块

typing

新的 typing 临时模块为函数类型注解提供了标准定义和工具。有关更多信息,请参阅类型提示

zipapp

新的 zipapp 模块(在 PEP 441 中指定)提供了一个 API 和命令行工具,用于创建可执行的 Python Zip 应用程序,该功能在 Python 2.6 中通过 bpo-1739468 引入,但在当时或之后都没有得到很好的宣传。

使用新模块,打包应用程序就像将所有文件(包括 __main__.py 文件)放入目录 myapp 并运行一样简单

$ python -m zipapp myapp
$ python myapp.pyz

该模块的实现由 Paul Moore 在 bpo-23491 中贡献。

参见

PEP 441 – 改进 Python ZIP 应用程序支持

改进的模块

argparse

ArgumentParser 类现在允许通过将 allow_abbrev 设置为 False 来禁用长选项的缩写用法。(由 Jonathan Paugh、Steven Bethard、paul j3 和 Daniel Eriksson 在 bpo-14910 中贡献。)

asyncio

由于 asyncio 模块是临时的,因此 Python 3.5 中引入的所有更改也已反向移植到 Python 3.4.x。

Python 3.4.0 以来 asyncio 模块中的显著更改

3.5.1 版中的更新

3.5.2 版中的更新

bz2

BZ2Decompressor.decompress 方法现在接受一个可选的 max_length 参数来限制解压数据的最大大小。(由 Nikolaus Rath 在 bpo-15955 中贡献。)

cgi

FieldStorage 类现在支持上下文管理器协议。(由 Berker Peksag 在 bpo-20289 中贡献。)

cmath

一个新的函数 isclose() 提供了一种测试近似相等性的方法。(由 Chris Barker 和 Tal Einat 在 bpo-24270 中贡献。)

code

InteractiveInterpreter.showtraceback() 方法现在会打印完整的链式回溯,就像交互式解释器一样。(由 Claudiu Popa 在 bpo-17442 中贡献。)

collections

OrderedDict 类现在用 C 实现,使其速度提高了 4 到 100 倍。(由 Eric Snow 在 bpo-16991 中贡献。)

OrderedDict.items()OrderedDict.keys()OrderedDict.values() 视图现在支持 reversed() 迭代。(由 Serhiy Storchaka 在 bpo-19505 中贡献。)

deque 类现在定义了 index()insert()copy(),并支持 +* 运算符。这使得 deque 可以被识别为 MutableSequence,并提高了它们与列表的可替换性。(由 Raymond Hettinger 在 bpo-23704 中贡献。)

namedtuple() 生成的文档字符串现在可以更新

Point = namedtuple('Point', ['x', 'y'])
Point.__doc__ += ': Cartesian coordinate'
Point.x.__doc__ = 'abscissa'
Point.y.__doc__ = 'ordinate'

(由 Berker Peksag 在 bpo-24064 中贡献。)

UserString 类现在实现了 __getnewargs__()__rmod__()casefold()format_map()isprintable()maketrans() 方法,以匹配 str 的相应方法。(由 Joe Jevnik 在 bpo-22189 中贡献。)

collections.abc

Sequence.index() 方法现在接受 startstop 参数,以匹配 tuplelist 等的相应方法。(由 Devin Jeanpierre 在 bpo-23086 中贡献。)

一个新的 Generator 抽象基类。(由 Stefan Behnel 在 bpo-24018 中贡献。)

新的 AwaitableCoroutineAsyncIteratorAsyncIterable 抽象基类。(由 Yury Selivanov 在 bpo-24184 中贡献。)

对于早期的 Python 版本,新 ABC 的反向移植可在外部 PyPI 包中找到。

compileall

一个新的 compileall 选项 -j N 允许同时运行 N 个工作进程执行并行字节码编译。compile_dir() 函数有一个相应的 workers 参数。(由 Claudiu Popa 在 bpo-16104 中贡献。)

另一个新选项 -r 允许控制子目录的最大递归级别。(由 Claudiu Popa 在 bpo-19628 中贡献。)

-q 命令行选项现在可以多次指定,在这种情况下,所有输出(包括错误)都将被抑制。compile_dir()compile_file()compile_path() 中相应的 quiet 参数现在可以接受一个整数值,表示输出抑制的级别。(由 Thomas Kluyver 在 bpo-21338 中贡献。)

concurrent.futures

Executor.map() 方法现在接受一个 chunksize 参数,允许批量处理任务,以在使用 ProcessPoolExecutor() 时提高性能。(由 Dan O’Reilly 在 bpo-11271 中贡献。)

ThreadPoolExecutor 构造函数中的工作进程数量现在是可选的。默认值是 CPU 数量的 5 倍。(由 Claudiu Popa 在 bpo-21527 中贡献。)

configparser

configparser 现在提供了一种通过在 ConfigParser 构造函数中指定转换器字典,或在 ConfigParser 子类中将它们定义为方法来定制值转换的方式。在解析器实例中定义的转换器由其节代理继承。

示例

>>> import configparser
>>> conv = {}
>>> conv['list'] = lambda v: [e.strip() for e in v.split() if e.strip()]
>>> cfg = configparser.ConfigParser(converters=conv)
>>> cfg.read_string("""
... [s]
... list = a b c d e f g
... """)
>>> cfg.get('s', 'list')
'a b c d e f g'
>>> cfg.getlist('s', 'list')
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> section = cfg['s']
>>> section.getlist('list')
['a', 'b', 'c', 'd', 'e', 'f', 'g']

(由 Łukasz Langa 在 bpo-18159 中贡献。)

contextlib

新的 redirect_stderr() 上下文管理器(类似于 redirect_stdout())使得实用脚本更容易处理将输出写入 sys.stderr 且不提供任何重定向选项的僵硬 API

>>> import contextlib, io, logging
>>> f = io.StringIO()
>>> with contextlib.redirect_stderr(f):
...     logging.warning('warning')
...
>>> f.getvalue()
'WARNING:root:warning\n'

(由 Berker Peksag 在 bpo-22389 中贡献。)

csv

writerow() 方法现在支持任意可迭代对象,而不仅仅是序列。(由 Serhiy Storchaka 在 bpo-23171 中贡献。)

curses

新的 update_lines_cols() 函数更新 LINESCOLS 模块变量。这对于检测手动屏幕大小调整很有用。(由 Arnon Yaari 在 bpo-4254 中贡献。)

dbm

当标志值为 "n" 时,dumb.open 总是创建一个新的数据库。(由 Claudiu Popa 在 bpo-18039 中贡献。)

difflib

现在可以通过使用新的仅关键字参数 charset 来自定义 HtmlDiff.make_file() 生成的 HTML 文档的字符集。HTML 文档的默认字符集从 "ISO-8859-1" 更改为 "utf-8"。(由 Berker Peksag 在 bpo-2052 中贡献。)

函数 diff_bytes() 现在可以比较字节字符串列表。这修复了 Python 2 中的一个回归。(由 Terry J. Reedy 和 Greg Ward 在 bpo-17445 中贡献。)

distutils

buildbuild_ext 命令现在都接受 -j 选项,以启用扩展模块的并行构建。(由 Antoine Pitrou 在 bpo-5309 中贡献。)

distutils 模块现在支持 xz 压缩,可以通过将 xztar 作为参数传递给 bdist --format 来启用。(由 Serhiy Storchaka 在 bpo-16314 中贡献。)

doctest

如果 module 不包含文档字符串,DocTestSuite() 函数将返回一个空的 unittest.TestSuite,而不是引发 ValueError。(由 Glenn Jones 在 bpo-15916 中贡献。)

email

一个新的策略选项 Policy.mangle_from_ 控制电子邮件正文中以 "From " 开头的行是否由生成器添加 ">" 字符前缀。对于 compat32,默认值为 True,对于所有其他策略,默认值为 False。(由 Milan Oberkirch 在 bpo-20098 中贡献。)

一个新的 Message.get_content_disposition() 方法提供了方便访问 Content-Disposition 标头的规范值。(由 Abhilash Raj 在 bpo-21083 中贡献。)

一个新的策略选项 EmailPolicy.utf8 可以设置为 True,以使用 UTF-8 字符集而不是编码词来编码电子邮件标头。这使得 Messages 可以根据 RFC 6532 进行格式化,并与支持 RFC 6531 SMTPUTF8 扩展的 SMTP 服务器一起使用。(由 R. David Murray 在 bpo-24211 中贡献。)

mime.text.MIMEText 构造函数现在接受一个 charset.Charset 实例。(由 Claude Paroz 和 Berker Peksag 在 bpo-16324 中贡献。)

enum

如果只提供了 namesEnum 可调用对象有一个新的参数 start,用于指定枚举值的初始编号

>>> Animal = enum.Enum('Animal', 'cat dog', start=10)
>>> Animal.cat
<Animal.cat: 10>
>>> Animal.dog
<Animal.dog: 11>

(由 Ethan Furman 在 bpo-21706 中贡献。)

faulthandler

enable()register()dump_traceback()dump_traceback_later() 函数现在除了接受文件类对象外,还接受文件描述符。(由 Wei Wu 在 bpo-23566 中贡献。)

functools

lru_cache() 的大部分机制现在都在 C 语言中实现,这使其显著加快。(由 Matt Joiner、Alexey Kachayev 和 Serhiy Storchaka 在 bpo-14373 中贡献。)

glob

iglob()glob() 函数现在支持使用 "**" 模式进行子目录递归搜索。(由 Serhiy Storchaka 在 bpo-13968 中贡献。)

gzip

GzipFile 构造函数的 mode 参数现在接受 "x" 以请求独占创建。(由 Tim Heaney 在 bpo-19222 中贡献。)

heapq

merge() 中的元素比较现在可以通过在新的可选 key 关键字参数中传递 key 函数 进行自定义,并且可以使用新的可选 reverse 关键字参数来反转元素比较

>>> import heapq
>>> a = ['9', '777', '55555']
>>> b = ['88', '6666']
>>> list(heapq.merge(a, b, key=len))
['9', '88', '777', '6666', '55555']
>>> list(heapq.merge(reversed(a), reversed(b), key=len, reverse=True))
['55555', '6666', '777', '88', '9']

(由 Raymond Hettinger 在 bpo-13742 中贡献。)

http

一个新的 HTTPStatus 枚举,定义了一组 HTTP 状态码、原因短语和用英语编写的长描述。(由 Demian Brecht 在 bpo-21793 中贡献。)

http.client

当远程服务器连接意外关闭时,HTTPConnection.getresponse() 现在会引发 RemoteDisconnected 异常。此外,如果引发 ConnectionErrorRemoteDisconnected 是其子类),客户端套接字现在会自动关闭,并在下次请求时重新连接

import http.client
conn = http.client.HTTPConnection('www.python.org')
for retries in range(3):
    try:
        conn.request('GET', '/')
        resp = conn.getresponse()
    except http.client.RemoteDisconnected:
        pass

(由 Martin Panter 在 bpo-3566 中贡献。)

idlelib 和 IDLE

由于 idlelib 实现了 IDLE shell 和编辑器,并且不打算被其他程序导入,因此它在每个版本中都得到了改进。有关自 3.4.0 以来以及未来 3.5.x 版本中所做的更改的累积列表,请参阅 Lib/idlelib/NEWS.txt。该文件也可以从 IDLE 的 Help ‣ About IDLE 对话框中获取。

imaplib

IMAP4 类现在支持 上下文管理器 协议。在 with 语句中使用时,IMAP4 LOGOUT 命令将在块结束时自动调用。(由 Tarek Ziadé 和 Serhiy Storchaka 在 bpo-4972 中贡献。)

imaplib 模块现在通过 IMAP4.enable() 方法支持 RFC 5161 (ENABLE 扩展) 和 RFC 6855 (UTF-8 支持)。一个新的 IMAP4.utf8_enabled 属性跟踪是否启用了 RFC 6855 支持。(由 Milan Oberkirch、R. David Murray 和 Maciej Szulik 在 bpo-21800 中贡献。)

根据 RFC 建议,imaplib 模块现在自动使用 UTF-8 编码非 ASCII 字符串的用户名和密码。(由 Milan Oberkirch 在 bpo-21800 中贡献。)

imghdr

what() 函数现在识别 OpenEXR 格式 (由 Martin Vignali 和 Claudiu Popa 在 bpo-20295 中贡献),以及 WebP 格式 (由 Fabrice Aneche 和 Claudiu Popa 在 bpo-20197 中贡献)。

importlib

util.LazyLoader 类允许在启动时间重要的应用程序中进行模块的延迟加载。(由 Brett Cannon 在 bpo-17621 中贡献。)

abc.InspectLoader.source_to_code() 方法现在是一个静态方法。这使得通过运行 exec(code, module.__dict__) 从字符串编译的代码初始化模块对象变得更容易。(由 Brett Cannon 在 bpo-21156 中贡献。)

新的 util.module_from_spec() 函数现在是创建新模块的首选方式。与直接创建 types.ModuleType 实例不同,这个新函数将根据传入的规范对象设置各种导入控制属性。(由 Brett Cannon 在 bpo-20383 中贡献。)

inspect

SignatureParameter 类现在都是可序列化和可哈希的。(由 Yury Selivanov 在 bpo-20726bpo-20334 中贡献。)

一个新的 BoundArguments.apply_defaults() 方法提供了一种为缺失参数设置默认值的方法

>>> def foo(a, b='ham', *args): pass
>>> ba = inspect.signature(foo).bind('spam')
>>> ba.apply_defaults()
>>> ba.arguments
OrderedDict([('a', 'spam'), ('b', 'ham'), ('args', ())])

(由 Yury Selivanov 在 bpo-24190 中贡献。)

一个新的类方法 Signature.from_callable() 使 Signature 的子类化更容易。(由 Yury Selivanov 和 Eric Snow 在 bpo-17373 中贡献。)

signature() 函数现在接受一个可选的关键字参数 follow_wrapped,当设置为 False 时,它会禁用自动跟踪 __wrapped__ 链接。(由 Yury Selivanov 在 bpo-20691 中贡献。)

新增了一组用于检查 协程函数协程对象 的新函数:iscoroutine()iscoroutinefunction()isawaitable()getcoroutinelocals()getcoroutinestate()。(由 Yury Selivanov 在 bpo-24017bpo-24400 中贡献。)

stack()trace()getouterframes()getinnerframes() 函数现在返回一个命名元组列表。(由 Daniel Shahaf 在 bpo-16808 中贡献。)

io

一个新的 BufferedIOBase.readinto1() 方法,最多只调用底层原始流的 RawIOBase.read()RawIOBase.readinto() 方法一次。(由 Nikolaus Rath 在 bpo-20578 中贡献。)

ipaddress

IPv4NetworkIPv6Network 类现在都接受 (address, netmask) 元组参数,以便从现有地址轻松构造网络对象

>>> import ipaddress
>>> ipaddress.IPv4Network(('127.0.0.0', 8))
IPv4Network('127.0.0.0/8')
>>> ipaddress.IPv4Network(('127.0.0.0', '255.0.0.0'))
IPv4Network('127.0.0.0/8')

(由 Peter Moody 和 Antoine Pitrou 在 bpo-16531 中贡献。)

IPv4AddressIPv6Address 类的新属性 reverse_pointer 返回反向 DNS PTR 记录的名称

>>> import ipaddress
>>> addr = ipaddress.IPv4Address('127.0.0.1')
>>> addr.reverse_pointer
'1.0.0.127.in-addr.arpa'
>>> addr6 = ipaddress.IPv6Address('::1')
>>> addr6.reverse_pointer
'1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa'

(由 Leon Weber 在 bpo-20480 中贡献。)

json

json.tool 命令行界面现在保留输入中 JSON 对象的键的顺序。新的 --sort-keys 选项可用于按字母顺序对键进行排序。(由 Berker Peksag 在 bpo-21650 中贡献。)

JSON 解码器现在引发 JSONDecodeError 而不是 ValueError,以提供更好的错误上下文信息。(由 Serhiy Storchaka 在 bpo-19361 中贡献。)

linecache

一个新的 lazycache() 函数可用于捕获非文件模块的信息,以便稍后通过 getline() 获取其行。这避免了在实际需要行之前进行 I/O 操作,而无需无限期地携带模块全局变量。(由 Robert Collins 在 bpo-17911 中贡献。)

locale

一个新的 delocalize() 函数可用于将字符串转换为标准化数字字符串,并考虑 LC_NUMERIC 设置

>>> import locale
>>> locale.setlocale(locale.LC_NUMERIC, 'de_DE.UTF-8')
'de_DE.UTF-8'
>>> locale.delocalize('1.234,56')
'1234.56'
>>> locale.setlocale(locale.LC_NUMERIC, 'en_US.UTF-8')
'en_US.UTF-8'
>>> locale.delocalize('1,234.56')
'1234.56'

(由 Cédric Krier 在 bpo-13918 中贡献。)

logging

所有日志方法(Logger log()exception()critical()debug() 等)现在都接受异常实例作为 exc_info 参数,此外还接受布尔值和异常元组

>>> import logging
>>> try:
...     1/0
... except ZeroDivisionError as ex:
...     logging.error('exception', exc_info=ex)
ERROR:root:exception

(由 Yury Selivanov 在 bpo-20537 中贡献。)

handlers.HTTPHandler 类现在接受一个可选的 ssl.SSLContext 实例来配置 HTTP 连接中使用的 SSL 设置。(由 Alex Gaynor 在 bpo-22788 中贡献。)

handlers.QueueListener 类现在接受一个 respect_handler_level 关键字参数,如果设置为 True,则会考虑处理程序级别将消息传递给处理程序。(由 Vinay Sajip 贡献。)

lzma

LZMADecompressor.decompress() 方法现在接受一个可选的 max_length 参数来限制解压缩数据的最大大小。(由 Martin Panter 在 bpo-15955 中贡献。)

math

math 模块中新增了两个常量:infnan。(由 Mark Dickinson 在 bpo-23185 中贡献。)

一个新的函数 isclose() 提供了一种测试近似相等性的方法。(由 Chris Barker 和 Tal Einat 在 bpo-24270 中贡献。)

新增了一个 gcd() 函数。 fractions.gcd() 函数现已弃用。(由 Mark Dickinson 和 Serhiy Storchaka 在 bpo-22486 中贡献。)

multiprocessing

sharedctypes.synchronized() 对象现在支持 上下文管理器 协议。(由 Charles-François Natali 在 bpo-21565 中贡献。)

operator

attrgetter()itemgetter()methodcaller() 对象现在支持序列化。(由 Josh Rosenberg 和 Serhiy Storchaka 在 bpo-22955 中贡献。)

新的 matmul()imatmul() 函数用于执行矩阵乘法。(由 Benjamin Peterson 在 bpo-21176 中贡献。)

os

新增了返回 DirEntry 对象迭代器的新函数 scandir()。如果可能,scandir() 会在扫描目录时提取文件属性,无需执行后续的系统调用来确定文件类型或属性,这可能会显著提高性能。(由 Ben Hoyt 在 Victor Stinner 的帮助下在 bpo-22524 中贡献。)

在 Windows 上,现在提供了一个新的 stat_result.st_file_attributes 属性。它对应于 GetFileInformationByHandle() 返回的 BY_HANDLE_FILE_INFORMATION 结构体的 dwFileAttributes 成员。(由 Ben Hoyt 在 bpo-21719 中贡献。)

urandom() 函数现在在 Linux 3.17 或更高版本上使用 getrandom() 系统调用,在 OpenBSD 5.6 或更高版本上使用 getentropy(),从而无需使用 /dev/urandom 并避免因潜在的文件描述符耗尽而导致的故障。(由 Victor Stinner 在 bpo-22181 中贡献。)

新的 get_blocking()set_blocking() 函数允许获取和设置文件描述符的阻塞模式 (O_NONBLOCK)。(由 Victor Stinner 在 bpo-22054 中贡献。)

truncate()ftruncate() 函数现在在 Windows 上受支持。(由 Steve Dower 在 bpo-23668 中贡献。)

新增了 os.path.commonpath() 函数,它返回每个传入路径名的最长公共子路径。与 os.path.commonprefix() 函数不同,它总是返回一个有效路径

>>> os.path.commonprefix(['/usr/lib', '/usr/local/lib'])
'/usr/l'

>>> os.path.commonpath(['/usr/lib', '/usr/local/lib'])
'/usr'

(由 Rafik Draoui 和 Serhiy Storchaka 在 bpo-10395 中贡献。)

pathlib

新的 Path.samefile() 方法可用于检查路径是否指向与另一个路径相同的文件,另一个路径可以是另一个 Path 对象,也可以是字符串

>>> import pathlib
>>> p1 = pathlib.Path('/etc/hosts')
>>> p2 = pathlib.Path('/etc/../etc/hosts')
>>> p1.samefile(p2)
True

(由 Vajrasky Kok 和 Antoine Pitrou 在 bpo-19775 中贡献。)

Path.mkdir() 方法现在接受一个新的可选参数 exist_ok,以匹配 mkdir -pos.makedirs() 的功能。(由 Berker Peksag 在 bpo-21539 中贡献。)

新增了一个 Path.expanduser() 方法来扩展 ~~user 前缀。(由 Serhiy Storchaka 和 Claudiu Popa 在 bpo-19776 中贡献。)

一个新的 Path.home() 类方法可用于获取表示用户主目录的 Path 实例。(由 Victor Salgado 和 Mayank Tripathi 在 bpo-19777 中贡献。)

新的 Path.write_text()Path.read_text()Path.write_bytes()Path.read_bytes() 方法简化了文件的读/写操作。

以下代码片段将创建或重写现有文件 ~/spam42

>>> import pathlib
>>> p = pathlib.Path('~/spam42')
>>> p.expanduser().write_text('ham')
3

(由 Christopher Welborn 在 bpo-20218 中贡献。)

pickle

现在可以使用早于协议版本 4 的 pickle 协议 序列化嵌套对象,例如未绑定的方法或嵌套类。协议版本 4 已经支持这些情况。(由 Serhiy Storchaka 在 bpo-23611 中贡献。)

poplib

一个新的 POP3.utf8() 命令启用 RFC 6856 (国际化电子邮件) 支持,如果 POP 服务器支持它。(由 Milan OberKirch 在 bpo-21804 中贡献。)

re

现在允许在后向断言中使用对固定长度组的引用和条件引用

>>> import re
>>> pat = re.compile(r'(a|b).(?<=\1)c')
>>> pat.match('aac')
<_sre.SRE_Match object; span=(0, 3), match='aac'>
>>> pat.match('bbc')
<_sre.SRE_Match object; span=(0, 3), match='bbc'>

(由 Serhiy Storchaka 在 bpo-9179 中贡献。)

正则表达式中捕获组的数量不再限制为 100。(由 Serhiy Storchaka 在 bpo-22437 中贡献。)

sub()subn() 函数现在用空字符串替换不匹配的组,而不是引发异常。(由 Serhiy Storchaka 在 bpo-1519638 中贡献。)

re.error 异常现在具有新的属性 msgpatternposlinenocolno,它们提供了更好的错误上下文信息

>>> re.compile("""
...     (?x)
...     .++
... """)
Traceback (most recent call last):
   ...
sre_constants.error: multiple repeat at position 16 (line 3, column 7)

(由 Serhiy Storchaka 在 bpo-22578 中贡献。)

readline

一个新的 append_history_file() 函数可用于将历史记录中指定数量的尾随元素追加到给定文件。(由 Bruno Cauet 在 bpo-22940 中贡献。)

selectors

新的 DevpollSelector 支持在 Solaris 上高效地 /dev/poll 轮询。(由 Giampaolo Rodola' 在 bpo-18931 中贡献。)

shutil

move() 函数现在接受 copy_function 参数,例如,如果移动时需要忽略文件元数据,则允许使用 copy() 函数而不是默认的 copy2()。(由 Claudiu Popa 在 bpo-19840 中贡献。)

make_archive() 函数现在支持 xztar 格式。(由 Serhiy Storchaka 在 bpo-5411 中贡献。)

信号

在 Windows 上,set_wakeup_fd() 函数现在也支持套接字句柄。(由 Victor Stinner 在 bpo-22018 中贡献。)

signal 模块中的各种 SIG* 常量已转换为 Enums。这允许在调试期间打印有意义的名称,而不是整数“魔术数字”。(由 Giampaolo Rodola' 在 bpo-21076 中贡献。)

smtpd

SMTPServerSMTPChannel 类现在都接受 decode_data 关键字参数,以确定 SMTP 事务的 DATA 部分是否使用 "utf-8" 编解码器解码,或者作为字节字符串提供给 SMTPServer.process_message() 方法。出于向后兼容性原因,默认值为 True,但在 Python 3.6 中将更改为 False。如果 decode_data 设置为 False,则 process_message 方法必须准备好接受关键字参数。(由 Maciej Szulik 在 bpo-19662 中贡献。)

如果 decode_data 已设置为 True,则 SMTPServer 类现在会宣传 8BITMIME 扩展 (RFC 6152)。如果客户端在 MAIL 命令上指定 BODY=8BITMIME,它将通过 mail_options 关键字传递给 SMTPServer.process_message()。(由 Milan Oberkirch 和 R. David Murray 在 bpo-21795 中贡献。)

SMTPServer 类现在还支持 SMTPUTF8 扩展 (RFC 6531: 国际化电子邮件)。如果客户端在 MAIL 命令上指定 SMTPUTF8 BODY=8BITMIME,它们将通过 mail_options 关键字传递给 SMTPServer.process_message()。正确处理 SMTPUTF8 数据是 process_message 方法的责任。(由 Milan Oberkirch 在 bpo-21725 中贡献。)

现在可以在 SMTPServer 构造函数中直接或通过名称解析提供 IPv6 地址,并使其成功连接。(由 Milan Oberkirch 在 bpo-14758 中贡献。)

smtplib

一个新的 SMTP.auth() 方法提供了一种方便的方式来实现自定义身份验证机制。(由 Milan Oberkirch 在 bpo-15014 中贡献。)

SMTP.set_debuglevel() 方法现在接受一个额外的调试级别 (2),该级别在调试消息中启用时间戳。(由 Gavin Chappell 和 Maciej Szulik 在 bpo-16914 中贡献。)

SMTP.sendmail()SMTP.send_message() 方法现在都支持 RFC 6531 (SMTPUTF8)。(由 Milan Oberkirch 和 R. David Murray 在 bpo-22027 中贡献。)

sndhdr

what()whathdr() 函数现在返回一个 namedtuple()。(由 Claudiu Popa 在 bpo-18615 中贡献。)

socket

带超时功能的函数现在使用单调时钟,而不是系统时钟。(由 Victor Stinner 在 bpo-22043 中贡献。)

一个新的 socket.sendfile() 方法允许通过套接字发送文件,方法是在 UNIX 上使用高性能的 os.sendfile() 函数,从而使上传速度比使用纯 socket.send() 快 2 到 3 倍。(由 Giampaolo Rodola' 在 bpo-17552 中贡献。)

socket.sendall() 方法不再每次接收或发送字节时重置套接字超时。套接字超时现在是发送所有数据的最大总持续时间。(由 Victor Stinner 在 bpo-23853 中贡献。)

socket.listen() 方法的 backlog 参数现在是可选的。默认情况下,它设置为 SOMAXCONN128,取较小者。(由 Charles-François Natali 在 bpo-21455 中贡献。)

ssl

内存 BIO 支持

(由 Geert Jansen 在 bpo-21965 中贡献。)

新增了 SSLObject 类,用于在 SSLSocket 的网络 I/O 功能不必要或不理想的情况下提供 SSL 协议支持。SSLObject 表示一个 SSL 协议实例,但不实现任何网络 I/O 方法,而是提供内存缓冲区接口。新的 MemoryBIO 类可用于在 Python 和 SSL 协议实例之间传递数据。

内存 BIO SSL 支持主要用于实现异步 I/O 的框架,对于这些框架,SSLSocket 的就绪模型(“select/poll”)效率低下。

一个新的 SSLContext.wrap_bio() 方法可用于创建新的 SSLObject 实例。

应用层协议协商支持

(由 Benjamin Peterson 在 bpo-20188 中贡献。)

在存在 OpenSSL 支持的情况下,ssl 模块现在实现了 RFC 7301 中描述的 应用层协议协商 TLS 扩展。

新的 SSLContext.set_alpn_protocols() 可用于指定套接字在 TLS 握手期间应宣传哪些协议。

新的 SSLSocket.selected_alpn_protocol() 返回在 TLS 握手期间选择的协议。HAS_ALPN 标志指示是否存在 ALPN 支持。

其他更改

新增了一个 SSLSocket.version() 方法来查询实际使用的协议版本。(由 Antoine Pitrou 在 bpo-20421 中贡献。)

SSLSocket 类现在实现了 SSLSocket.sendfile() 方法。(由 Giampaolo Rodola' 在 bpo-17552 中贡献。)

SSLSocket.send() 方法现在在非阻塞套接字上,如果操作会阻塞,则会引发 ssl.SSLWantReadErrorssl.SSLWantWriteError 异常。以前,它会返回 0。(由 Nikolaus Rath 在 bpo-20951 中贡献。)

根据 RFC 5280cert_time_to_seconds() 函数现在将输入时间解释为 UTC 而不是本地时间。此外,返回值始终是 int。(由 Akira Li 在 bpo-19940 中贡献。)

新的 SSLObject.shared_ciphers()SSLSocket.shared_ciphers() 方法返回客户端在握手期间发送的密码列表。(由 Benjamin Peterson 在 bpo-23186 中贡献。)

SSLSocket 类的 SSLSocket.do_handshake()SSLSocket.read()SSLSocket.shutdown()SSLSocket.write() 方法不再在每次接收或发送字节时重置套接字超时。套接字超时现在是方法的最大总持续时间。(由 Victor Stinner 在 bpo-23853 中贡献。)

match_hostname() 函数现在支持 IP 地址匹配。(由 Antoine Pitrou 在 bpo-23239 中贡献。)

sqlite3

Row 类现在完全支持序列协议,特别是 reversed() 迭代和切片索引。(由 Claudiu Popa 在 bpo-10203 中贡献;由 Lucas Sinclair、Jessica McKellar 和 Serhiy Storchaka 在 bpo-13583 中贡献。)

subprocess

新增了 run() 函数。它运行指定的命令并返回一个 CompletedProcess 对象,该对象描述了一个已完成的进程。新的 API 更一致,是 Python 代码中调用子进程的推荐方法,这些代码不需要保持与早期 Python 版本的兼容性。(由 Thomas Kluyver 在 bpo-23342 中贡献。)

示例:

>>> subprocess.run(["ls", "-l"])  # doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)

>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
  ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

>>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0,
stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n')

sys

一个新的 set_coroutine_wrapper() 函数允许设置一个全局钩子,每当 协程对象async def 函数创建时,该钩子就会被调用。相应的 get_coroutine_wrapper() 可用于获取当前设置的包装器。这两个函数都是 临时 的,仅用于调试目的。(由 Yury Selivanov 在 bpo-24017 中贡献。)

一个新的 is_finalizing() 函数可用于检查 Python 解释器是否正在 关闭。(由 Antoine Pitrou 在 bpo-22696 中贡献。)

sysconfig

Windows 上用户脚本目录的名称现在包含 Python 版本的头两个组件。(由 Paul Moore 在 bpo-23437 中贡献。)

tarfile

open() 函数的 mode 参数现在接受 "x" 以请求独占创建。(由 Berker Peksag 在 bpo-21717 中贡献。)

TarFile.extractall()TarFile.extract() 方法现在接受一个关键字参数 numeric_owner。如果设置为 True,则提取的文件和目录将由 tar 文件中的数字 uidgid 拥有。如果设置为 False(默认值,以及 3.5 版本之前的行为),它们将由 tar 文件中指定的命名用户和组拥有。(由 Michael Vogt 和 Eric Smith 在 bpo-23193 中贡献。)

TarFile.list() 现在接受一个可选的 members 关键字参数,可以将其设置为 TarFile.getmembers() 返回列表的子集。(由 Serhiy Storchaka 在 bpo-21549 中贡献。)

threading

Lock.acquire()RLock.acquire() 方法现在都使用单调时钟进行超时管理。(由 Victor Stinner 在 bpo-22043 中贡献。)

时间

monotonic() 函数现在始终可用。(由 Victor Stinner 在 bpo-22043 中贡献。)

timeit

可以使用新的命令行选项 -u--unit=U 来指定计时器输出的时间单位。支持的选项有 usecmsecsec。(由 Julian Gindi 在 bpo-18983 中贡献。)

timeit() 函数新增了一个 globals 参数,用于指定代码运行的命名空间。(由 Ben Roberts 在 bpo-2527 中贡献。)

tkinter

用于在 Windows 上设置 Tcl/Tk 环境的 tkinter._fix 模块已被 _tkinter 模块中的一个私有函数取代,该函数不会对环境变量进行永久性更改。(由 Zachary Ware 在 bpo-20035 中贡献。)

traceback

新的 walk_stack()walk_tb() 函数,方便遍历帧和 回溯对象。(由 Robert Collins 在 bpo-17911 中贡献。)

新的轻量级类:TracebackExceptionStackSummaryFrameSummary。(由 Robert Collins 在 bpo-17911 中贡献。)

print_tb()print_stack() 函数现在都支持 limit 参数的负值。(由 Dmitry Kazakov 在 bpo-22619 中贡献。)

types

一个新的 coroutine() 函数,用于将 生成器类生成器 对象转换为 可等待对象。(由 Yury Selivanov 在 bpo-24017 中贡献。)

新增了一个名为 CoroutineType 的类型,用于 async def 函数创建的 协程 对象。(由 Yury Selivanov 在 bpo-24400 中贡献。)

unicodedata

unicodedata 模块现在使用 Unicode 8.0.0 的数据。

unittest

TestLoader.loadTestsFromModule() 方法现在接受一个仅限关键字参数 pattern,该参数作为第三个参数传递给 load_tests。现在无论找到的包的路径是否与 pattern 匹配,都会检查其是否存在 load_tests,因为包名不可能匹配默认模式。(由 Robert Collins 和 Barry A. Warsaw 在 bpo-16662 中贡献。)

单元测试发现错误现在在 TestLoader 实例的 TestLoader.errors 属性中公开。(由 Robert Collins 在 bpo-19746 中贡献。)

新增命令行选项 --locals,用于在回溯中显示局部变量。(由 Robert Collins 在 bpo-22936 中贡献。)

unittest.mock

Mock 类有以下改进

  • 类构造函数新增了 unsafe 参数,该参数会使 mock 对象在属性名称以 "assert" 开头时引发 AttributeError。(由 Kushal Das 在 bpo-21238 中贡献。)

  • 新增 Mock.assert_not_called() 方法,用于检查 mock 对象是否被调用。(由 Kushal Das 在 bpo-21262 中贡献。)

MagicMock 类现在支持 __truediv__()__divmod__()__matmul__() 运算符。(由 Johannes Baiter 在 bpo-20968,以及 Håkan Lövdahl 在 bpo-23581bpo-23568 中贡献。)

在修补内置名称时,不再需要显式将 create=True 传递给 patch() 函数。(由 Kushal Das 在 bpo-17660 中贡献。)

urllib

新增 request.HTTPPasswordMgrWithPriorAuth 类,允许管理 HTTP 基本认证凭据,以消除不必要的 401 响应处理,或在第一次请求时无条件发送凭据,以便与返回 404 响应而不是 401 的服务器通信,如果未发送 Authorization 标头。(由 Matej Cepl 在 bpo-19494 和 Akshit Khurana 在 bpo-7159 中贡献。)

parse.urlencode() 函数新增了 quote_via 参数,在需要时提供了一种控制查询部分编码的方式。(由 Samwyse 和 Arnon Yaari 在 bpo-13866 中贡献。)

request.urlopen() 函数接受一个 ssl.SSLContext 对象作为 context 参数,该对象将用于 HTTPS 连接。(由 Alex Gaynor 在 bpo-22366 中贡献。)

parse.urljoin() 已更新,以使用 RFC 3986 语义来解析相对 URL,而不是 RFC 1808RFC 2396。(由 Demian Brecht 和 Senthil Kumaran 在 bpo-22118 中贡献。)

wsgiref

headers.Headers 类构造函数的 headers 参数现在是可选的。(由 Pablo Torres Navarrete 和 SilentGhost 在 bpo-5800 中贡献。)

xmlrpc

client.ServerProxy 类现在支持 上下文管理器 协议。(由 Claudiu Popa 在 bpo-20627 中贡献。)

client.ServerProxy 构造函数现在接受一个可选的 ssl.SSLContext 实例。(由 Alex Gaynor 在 bpo-22960 中贡献。)

xml.sax

SAX 解析器现在支持 xmlreader.InputSource 对象的字符流。(由 Serhiy Storchaka 在 bpo-2175 中贡献。)

parseString() 现在接受一个 str 实例。(由 Serhiy Storchaka 在 bpo-10590 中贡献。)

zipfile

ZIP 输出现在可以写入不可查找的流。(由 Serhiy Storchaka 在 bpo-23252 中贡献。)

ZipFile.open() 方法的 mode 参数现在接受 "x",以请求独占创建。(由 Serhiy Storchaka 在 bpo-21717 中贡献。)

其他模块级更改

mmapossaudiodevsocketsslcodecs 模块中的许多函数现在接受可写的 类字节对象。(由 Serhiy Storchaka 在 bpo-23001 中贡献。)

优化

os.walk() 函数在 POSIX 系统上速度提高了 3 到 5 倍,在 Windows 上速度提高了 7 到 20 倍。这是通过使用新的 os.scandir() 函数实现的,该函数公开了底层 readdirFindFirstFile/FindNextFile 系统调用的文件信息。(由 Ben Hoyt 在 Victor Stinner 的帮助下在 bpo-23605 中贡献。)

bytes(int) (用零字节填充) 的构造对于大型对象更快,并使用更少的内存。使用 calloc() 而不是 malloc() 来为这些对象分配内存。(由 Victor Stinner 在 bpo-21233 中贡献。)

ipaddress IPv4NetworkIPv6Network 的一些操作已大幅加速,例如 subnets()supernet()summarize_address_range()collapse_addresses()。速度可以提高 3 到 15 倍。(由 Antoine Pitrou、Michel Albert 和 Markus 在 bpo-21486bpo-21487bpo-20826bpo-23266 中贡献。)

ipaddress 对象的 pickle 序列化已优化,以生成明显更小的输出。(由 Serhiy Storchaka 在 bpo-23133 中贡献。)

io.BytesIO 上的许多操作现在速度提高了 50% 到 100%。(由 Serhiy Storchaka 在 bpo-15381 和 David Wilson 在 bpo-22003 中贡献。)

marshal.dumps() 函数现在更快:版本 3 和 4 提高了 65–85%,版本 0 到 2 在典型数据上提高了 20–25%,在最佳情况下甚至提高了 5 倍。(由 Serhiy Storchaka 在 bpo-20416bpo-23344 中贡献。)

UTF-32 编码器现在速度提高了 3 到 7 倍。(由 Serhiy Storchaka 在 bpo-15027 中贡献。)

正则表达式现在解析速度提高了 10%。(由 Serhiy Storchaka 在 bpo-19380 中贡献。)

json.dumps() 函数已优化,使其在 ensure_ascii=False 时与在 ensure_ascii=True 时一样快。(由 Naoki Inada 在 bpo-23206 中贡献。)

PyObject_IsInstance()PyObject_IsSubclass() 函数在第二个参数的元类是 type 的常见情况下已加速。(由 Georg Brandl 在 bpo-22540 中贡献。)

方法缓存略有改进,在某些基准测试中性能提高了 5%。(由 Antoine Pitrou 在 bpo-22847 中贡献。)

random 模块的对象在 64 位构建中现在使用减少 50% 的内存。(由 Serhiy Storchaka 在 bpo-23488 中贡献。)

property() getter 调用速度提高了 25%。(由 Joe Jevnik 在 bpo-23910 中贡献。)

fractions.Fraction 的实例化现在速度提高了 30%。(由 Stefan Behnel 在 bpo-22464 中贡献。)

字符串方法 find()rfind()split()partition()in 字符串运算符在搜索 1 字符子字符串时现在显著更快。(由 Serhiy Storchaka 在 bpo-23573 中贡献。)

构建和 C API 更改

新增了 calloc 函数

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

新增编码/解码辅助函数

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

新增 PyCodec_NameReplaceErrors() 函数,用于将 Unicode 编码错误替换为 \N{...} 转义序列。(由 Serhiy Storchaka 在 bpo-19676 中贡献。)

新增 PyErr_FormatV() 函数,类似于 PyErr_Format(),但接受 va_list 参数。(由 Antoine Pitrou 在 bpo-18711 中贡献。)

新增 PyExc_RecursionError 异常。(由 Georg Brandl 在 bpo-19235 中贡献。)

PEP 489 引入了新的 PyModule_FromDefAndSpec()PyModule_FromDefAndSpec2()PyModule_ExecDef() 函数——多阶段扩展模块初始化。(由 Petr Viktorin 在 bpo-24268 中贡献。)

新的 PyNumber_MatrixMultiply()PyNumber_InPlaceMatrixMultiply() 函数,用于执行矩阵乘法。(由 Benjamin Peterson 在 bpo-21176 中贡献。详情请参阅 PEP 465。)

PyTypeObject.tp_finalize 插槽现在是稳定 ABI 的一部分。

Windows 构建现在需要 Microsoft Visual C++ 14.0,该版本可在 Visual Studio 2015 中获取。

在某些平台上,扩展模块的文件名现在包含平台信息标签(该标签是可选的,CPython 将导入没有它的扩展,但如果标签存在且不匹配,则不会加载扩展)

  • 在 Linux 上,扩展模块文件名以 .cpython-<major><minor>m-<architecture>-<os>.pyd 结尾

    • <major> 是 Python 版本的主版本号;对于 Python 3.5,这是 3

    • <minor> 是 Python 版本的次版本号;对于 Python 3.5,这是 5

    • <architecture> 是构建扩展模块以运行的硬件架构。最常见的是 32 位 Intel 平台的 i386 或 64 位 Intel (和 AMD) 平台的 x86_64

    • <os> 始终是 linux-gnu,除非是为在 64 位平台上与 32 位 ABI 通信而构建的扩展,在这种情况下它是 linux-gnu32 (并且 <architecture> 将是 x86_64)。

  • 在 Windows 上,扩展模块文件名以 <debug>.cp<major><minor>-<platform>.pyd 结尾

    • <major> 是 Python 版本的主版本号;对于 Python 3.5,这是 3

    • <minor> 是 Python 版本的次版本号;对于 Python 3.5,这是 5

    • <platform> 是构建扩展模块的平台,对于 Win32 是 win32,对于 Win64 是 win_amd64,对于 Windows Itanium 64 是 win_ia64,对于 ARM 上的 Windows 是 win_arm

    • 如果在调试模式下构建,<debug> 将是 _d,否则为空。

  • 在 OS X 平台上,扩展模块文件名现在以 -darwin.so 结尾。

  • 在所有其他平台上,扩展模块文件名与 Python 3.4 相同。

已弃用

新关键字

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

已废弃的 Python 行为

在生成器内部引发 StopIteration 异常现在将生成一个静默的 PendingDeprecationWarning,在 Python 3.6 中将变为非静默的废弃警告,并在 Python 3.7 中触发 RuntimeError。有关详细信息,请参阅 PEP 479: 更改生成器内部的 StopIteration 处理方式

不支持的操作系统

Windows XP 不再受 Microsoft 支持,因此,根据 PEP 11,CPython 3.5 不再正式支持此操作系统。

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

formatter 模块现在已完全废弃,并仍计划在 Python 3.6 中移除。

asyncio.async() 函数已被废弃,推荐使用 ensure_future()

smtpd 模块过去总是使用 utf-8 编解码器解码电子邮件消息的 DATA 部分。现在可以通过 SMTPServer 的新 decode_data 关键字来控制。默认值为 True,但此默认值已被废弃。请指定具有适当值的 decode_data 关键字以避免废弃警告。

直接将值赋给 http.cookies.Morsel 对象的 keyvaluecoded_value 已被废弃。请改用 set() 方法。此外,set() 的未文档化参数 LegalChars 已被废弃,现在将被忽略。

将格式字符串作为关键字参数 format_string 传递给 string.Formatter 类的 format() 方法已废弃。(由 Serhiy Storchaka 在 bpo-23671 中贡献。)

platform.dist()platform.linux_distribution() 函数现在已废弃。Linux 发行版使用太多不同的方式来描述自己,因此该功能留给了软件包。(由 Vajrasky Kok 和 Berker Peksag 在 bpo-1322 中贡献。)

inspect.Signature 的先前未文档化的 from_functionfrom_builtin 方法已被废弃。请改用新的 Signature.from_callable() 方法。(由 Yury Selivanov 在 bpo-24248 中贡献。)

inspect.getargspec() 函数已被废弃,并计划在 Python 3.6 中移除。(详情请参阅 bpo-20438。)

inspect getfullargspec()getcallargs()formatargspec() 函数已被废弃,推荐使用 inspect.signature() API。(由 Yury Selivanov 在 bpo-20438 中贡献。)

getargvalues()formatargvalues() 函数在 Python 3.5.0 发布时意外地被标记为废弃。

在字符串模式或 re.ASCII 中使用 re.LOCALE 标志现在已被废弃。(由 Serhiy Storchaka 在 bpo-22407 中贡献。)

在正则表达式模式和替换模式中,使用由 '\' 和 ASCII 字母组成的不被识别的特殊序列现在会引发废弃警告,并将在 Python 3.6 中被禁止。(由 Serhiy Storchaka 在 bpo-23622 中贡献。)

unittest.TestLoader.loadTestsFromModule() 方法的未文档化和非官方的 use_load_tests 默认参数现在已被废弃并忽略。(由 Robert Collins 和 Barry A. Warsaw 在 bpo-16662 中贡献。)

已移除

API 和功能移除

以下过时且先前已废弃的 API 和功能已被移除

  • email 包已删除 __version__ 属性。email 代码已长时间未与标准库分开提供,且 __version__ 字符串在最近几个版本中未更新。

  • ftplib 模块中的内部 Netrc 类在 3.4 中已废弃,现在已被移除。(由 Matt Chaput 在 bpo-6623 中贡献。)

  • .pyo 文件的概念已被移除。

  • 在临时 asyncio 模块中的 JoinableQueue 类在 3.4.4 中已废弃,现在已被移除。(由 A. Jesse Jiryu Davis 在 bpo-23464 中贡献。)

移植到 Python 3.5

本节列出了前面描述过的变更以及其他可能需要修改代码的 bug 修复。

Python 行为的改变

  • 由于疏忽,早期 Python 版本错误地接受了以下语法

    f(1 for x in [1], *args)
    f(1 for x in [1], **kwargs)
    

    Python 3.5 现在正确地引发 SyntaxError,因为生成器表达式如果不是函数的唯一参数,则必须用括号括起来。

Python API 的变化

  • PEP 475:系统调用现在在被信号中断时会重试,而不是在 Python 信号处理程序不引发异常时引发 InterruptedError

  • 在 Python 3.5 之前,如果 datetime.time 对象表示 UTC 午夜,则认为它为假。此行为被认为是晦涩且容易出错的,已在 Python 3.5 中移除。有关详细信息,请参阅 bpo-13936

  • ssl.SSLSocket.send() 方法现在在非阻塞套接字上如果操作会阻塞,则会引发 ssl.SSLWantReadErrorssl.SSLWantWriteError。以前,它会返回 0。(由 Nikolaus Rath 在 bpo-20951 中贡献。)

  • 生成器的 __name__ 属性现在从函数名称设置,而不是从代码名称设置。使用 gen.gi_code.co_name 检索代码名称。生成器还具有新的 __qualname__ 属性,即限定名称,现在用于表示生成器 (repr(gen))。(由 Victor Stinner 在 bpo-21205 中贡献。)

  • 已移除 HTMLParserHTMLParser.error() 的废弃“严格”模式和参数,以及 HTMLParserError 异常。(由 Ezio Melotti 在 bpo-15114 中贡献。) HTMLParserconvert_charrefs 参数现在默认为 True。(由 Berker Peksag 在 bpo-21047 中贡献。)

  • 尽管它不是 API 的正式部分,但为了移植目的(即:修复测试),值得注意的是,以前形式为“'sometype' 不支持缓冲区协议”的错误消息现在形式为“需要 类字节对象,而不是 'sometype'”。(由 Ezio Melotti 在 bpo-16518 中贡献。)

  • 如果当前目录设置为不再存在的目录,则不再引发 FileNotFoundError,而是 find_spec() 将返回 None,但 sys.path_importer_cache 中缓存 None,这与典型情况不同 (bpo-22834)。

  • http.clienthttp.server 中的 HTTP 状态代码和消息被重构为一个公共的 HTTPStatus 枚举。为了向后兼容,http.clienthttp.server 中的值仍然可用。(由 Demian Brecht 在 bpo-21793 中贡献。)

  • 当导入加载器定义 exec_module() 时,现在也期望它定义 create_module() (现在会引发 DeprecationWarning,在 Python 3.6 中将是错误)。如果加载器继承自 importlib.abc.Loader,则无需执行任何操作,否则只需定义 create_module() 返回 None。(由 Brett Cannon 在 bpo-23014 中贡献。)

  • re.split() 函数总是忽略空模式匹配,因此 "x*" 模式与 "x+" 的工作方式相同,并且 "\b" 模式从不起作用。现在,如果模式可能匹配空字符串,re.split() 会引发警告。为了兼容性,请使用从不匹配空字符串的模式(例如 "x+" 而不是 "x*")。只能匹配空字符串的模式(例如 "\b")现在会引发错误。(由 Serhiy Storchaka 在 bpo-22818 中贡献。)

  • http.cookies.Morsel 字典式接口已实现自洽:morsel 比较现在考虑 keyvaluecopy() 现在返回 Morsel 实例而不是 dict,并且 update() 现在如果更新字典中的任何键无效将引发异常。此外,set() 的未文档化 LegalChars 参数已被废弃并现在被忽略。(由 Demian Brecht 在 bpo-2211 中贡献。)

  • PEP 488 已从 Python 中移除 .pyo 文件,并在 .pyc 文件名中引入了可选的 opt- 标签。importlib.util.cache_from_source() 增加了 optimization 参数以帮助控制 opt- 标签。因此,该函数的 debug_override 参数现已废弃。.pyo 文件也不再支持作为 Python 解释器的文件参数,因此单独分发时没有任何用途(即无源代码分发)。由于 Python 3.5 中字节码的魔术数字已更改,因此无论此 PEP 如何,所有旧版 Python 的 .pyo 文件都无效。

  • socket 模块现在在 Linux 3.6 及更高版本上导出 CAN_RAW_FD_FRAMES 常量。

  • ssl.cert_time_to_seconds() 函数现在根据 RFC 5280 将输入时间解释为 UTC,而不是本地时间。此外,返回值始终是 int。(由 Akira Li 在 bpo-19940 中贡献。)

  • pygettext.py 工具现在在 POT-Creation-Date 标头中使用标准 +NNNN 时区格式。

  • smtplib 模块现在使用 sys.stderr 而不是以前的模块级 stderr 变量进行调试输出。如果您的(测试)程序依赖于修补模块级变量来捕获调试输出,则需要将其更新为捕获 sys.stderr。

  • str.startswith()str.endswith() 方法在找到空字符串且索引完全超出范围时不再返回 True。(由 Serhiy Storchaka 在 bpo-24284 中贡献。)

  • inspect.getdoc() 函数现在返回从基类继承的文档字符串。如果继承的文档是适当的,则不再需要重复文档字符串。要抑制继承的字符串,必须指定空字符串(或者可以填充文档)。此更改会影响 pydoc 模块和 help() 函数的输出。(由 Serhiy Storchaka 在 bpo-15582 中贡献。)

  • 嵌套的 functools.partial() 调用现在被扁平化。如果您依赖于以前的行为,您现在可以向 functools.partial() 对象添加属性,或者您可以创建 functools.partial() 的子类。(由 Alexander Belopolsky 在 bpo-7830 中贡献。)

C API 的变化

  • 已移除 (非公共) PyMemoryViewObject 结构中未文档化的 format 成员。所有依赖 memoryobject.h 中相关部分的扩展都必须重建。

  • PyMemAllocator 结构已重命名为 PyMemAllocatorEx,并添加了一个新的 calloc 字段。

  • 移除了泄漏引用的未文档化宏 PyObject_REPR()。在类似 PyUnicode_FromFormat() 的函数中使用格式字符 %R 来格式化对象的 repr()。(由 Serhiy Storchaka 在 bpo-22453 中贡献。)

  • 由于缺少 __module__ 属性会破坏 pickling 和内省,因此现在对于没有 __module__ 属性的内置类型会引发废弃警告。这在将来会是一个 AttributeError。(由 Serhiy Storchaka 在 bpo-20204 中贡献。)

  • 作为 PEP 492 实现的一部分,PyTypeObjecttp_reserved 插槽被 tp_as_async 插槽取代。有关新类型、结构和函数,请参阅 协程对象

Python 3.5.4 中的显著变化

新的 make regen-all 构建目标

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

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

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

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

3.5.4 版本新增。

移除 make touch 构建目标

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

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

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

3.5.4 版本更改。