Python 3.5 有什么新变化

这篇文章介绍了 Python 3.5 相比 3.4 增加的新特性。 Python 3.5 发布于 2015 年 9 月 13 日。 更完整的变化清单请参阅 changelog [https://docs.python.org/3.5/whatsnew/changelog.html]。

参见

PEP 478 [https://peps.python.org/pep-0478/] - Python 3.5 发布计划

摘要 — 发布重点

新的语法特性:

  • PEP 492, 使用 async 和 await 语法实现协程。

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

  • PEP 448, 额外的解包通用化。

新的库模块:

新的内置特性:

CPython 实现的改进:

  • LC_TYPE 语言区域为 POSIX 语言区域(即 C 语言区域)时,sys.stdinsys.stdout 现在将使用 surrogateescape 错误处理器,而不是 strict 错误处理器。 (由 Victor Stinner 在 bpo-19977 [https://bugs.python.org/issue?@action=redirect&bpo=19977] 中贡献。)

  • .pyo 文件已不再被使用而是被替换为一个更灵活的方案即在 .pyc 名称中显式地包括优化级别。 (参见 PEP 488 概览。)

  • 内置与扩展模块现在将经过多阶段的过程被初始化,这类似于 Python 模块的加载方式。 (参见 PEP 489 概览。)

标准库中的重大改进:

安全改进:

Windows改进:

  • 使用新的 Windows 安装器替代了旧版 MSI。 请参阅 在Windows上使用 Python 了解详情。

  • Windows 编译版现在使用 Microsoft Visual C++ 14.0,扩展模块也应当使用同一版本。

请继续阅读有关针对用户的改变的完整清单,包括许多其他较小的改进、CPython 优化、弃用以及潜在的移植问题。

新的特性

PEP 492 - 使用 async 和 await 语法实现协程

PEP 492 [https://peps.python.org/pep-0492/] 通过添加 可等待对象, 协程函数, 异步迭代异步上下文管理器 极大地改善了 Python 对异步编程的支持。

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

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

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

PEP 492 还增加了 async for 语句用于方便地迭代异步可迭代对象。

一个使用新语法编写的基本 HTTP 客户端示例:

  1. import asyncio
  2.  
  3. async def http_get(domain):
  4. reader, writer = await asyncio.open_connection(domain, 80)
  5.  
  6. writer.write(b'\r\n'.join([
  7. b'GET HTTP1.1',
  8. b'Host: %b' % domain.encode('latin-1'),
  9. b'Connection: close',
  10. b'', b''
  11. ]))
  12.  
  13. async for line in reader:
  14. print('>>>', line)
  15.  
  16. writer.close()
  17.  
  18. loop = asyncio.get_event_loop()
  19. try:
  20. loop.run_until_complete(http_get('example.com'))
  21. finally:
  22. loop.close()

与异步迭代类似,增加了用于异步上下文管理器的新语法。 以下代码:

  1. import asyncio
  2.  
  3. async def coro(name, lock):
  4. print('coro {}: waiting for lock'.format(name))
  5. async with lock:
  6. print('coro {}: holding the lock'.format(name))
  7. await asyncio.sleep(1)
  8. print('coro {}: releasing the lock'.format(name))
  9.  
  10. loop = asyncio.get_event_loop()
  11. lock = asyncio.Lock()
  12. coros = asyncio.gather(coro(1, lock), coro(2, lock))
  13. try:
  14. loop.run_until_complete(coros)
  15. finally:
  16. loop.close()

将输出:

  1. coro 2: waiting for lock
  2. coro 2: holding the lock
  3. coro 1: waiting for lock
  4. coro 2: releasing the lock
  5. coro 1: holding the lock
  6. coro 1: releasing the lock

请注意 async forasync with 都只能在通过 async def 声明的协程函数中使用。

协程函数应当在兼容的事件循环内部运行,例如 asyncio 循环

备注

在 3.5.2 版本发生变更: 从 CPython 3.5.2 开始,__aiter__ 可以直接返回 异步迭代器。 返回 awaitable 对象将会导致 PendingDeprecationWarning

详情参见文档的 异步迭代器 一节。

参见

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

PEP 465 [https://peps.python.org/pep-0465/] 增加了用于矩阵乘法的 @ 中缀运算符。 目前,还没有内置的 Python 类型实现这个新运算符,不过,它可通过定义 __matmul__(), __rmatmul__()__imatmul__() 分别用于常规、反射和原地矩阵乘法来实现。 这些方法的语义与定义其他中缀算术运算符的方法类似。

矩阵乘法在数学,科学,工程学的许多领域中是一种常见的操作,使用 @ 运算符可以编写更简洁的代码:

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

代替:

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

NumPy 1.10 支持新的运算符:

  1. >>> import numpy
  2.  
  3. >>> x = numpy.ones(3)
  4. >>> x
  5. array([ 1., 1., 1.])
  6.  
  7. >>> m = numpy.eye(3)
  8. >>> m
  9. array([[ 1., 0., 0.],
  10. [ 0., 1., 0.],
  11. [ 0., 0., 1.]])
  12.  
  13. >>> x @ m
  14. array([ 1., 1., 1.])

参见

PEP 448 - 进一步的解包标准化

PEP 448 [https://peps.python.org/pep-0448/] 扩展了 * 可迭代对象解包操作符和 ** 字典解包操作符的允许使用范围。 现在将可以在 函数调用 中使用任意数量的解包操作:

  1. >>> print(*[1], *[2], 3, *[4, 5])
  2. 1 2 3 4 5
  3.  
  4. >>> def fn(a, b, c, d):
  5. ... print(a, b, c, d)
  6. ...
  7.  
  8. >>> fn(**{'a': 1, 'c': 3}, **{'b': 2, 'd': 4})
  9. 1 2 3 4

类似地,元组、列表、集合与字典表示形式也允许多重解包 (参见 表达式列表字典显示):

  1. >>> *range(4), 4
  2. (0, 1, 2, 3, 4)
  3.  
  4. >>> [*range(4), 4]
  5. [0, 1, 2, 3, 4]
  6.  
  7. >>> {*range(4), 4, *(5, 6, 7)}
  8. {0, 1, 2, 3, 4, 5, 6, 7}
  9.  
  10. >>> {'x': 1, **{'y': 2}}
  11. {'x': 1, 'y': 2}

参见

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

PEP 461 [https://peps.python.org/pep-0461/] 增加了 % 插值运算符bytesbytearray 的支持。

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

示例:

  1. >>> b'Hello %b!' % b'World'
  2. b'Hello World!'
  3.  
  4. >>> b'x=%i y=%f' % (1, 2.5)
  5. b'x=1 y=2.500000'

Unicode 对于 %b 来说是不允许的,但对 %a 来说则是可接受的 (等价于 repr(obj).encode('ascii', 'backslashreplace')):

  1. >>> b'Hello %b!' % 'World'
  2. Traceback (most recent call last):
  3. File "<stdin>", line 1, in <module>
  4. TypeError: %b requires bytes, or an object that implements __bytes__, not 'str'
  5.  
  6. >>> b'price: %a' % '10€'
  7. b"price: '10\\u20ac'"

请注意 %s%r 转换类型虽然受到支持,但应当只被用于需要与 Python 2 保持兼容性的代码中。

参见

PEP 484 —— 类型提示

函数标注语法自 3.0 版起即已成为 Python 的特性 ( PEP 3107 [https://peps.python.org/pep-3107/]),标注的语义尚未得到定义。

经验表明大多数函数标注的使用都是为了向函数形参和返回值提供类型提示。 很显然如果标准库可以包括用于类型标注的基本定义和工具,对 Python 用户来说将大有裨益。

PEP 484 [https://peps.python.org/pep-0484/] 引入了一个 暂定模块 来提供这些标准定义和工具,以及针对标注不可用的场合的一些惯例。

例如,以下是一个在标注中声明了参数和返回值类型的简单函数:

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

虽然这些标注可在运行时通过常用的 __annotations__ 属性来访问,但是 不会在运行时进行自动类型检查。 作为替代,应该会为按需执行源代码分析提供一个单独的离线版类型检查器 (例如 mypy [https://mypy-lang.org])。

类型系统支持合并、泛型类型以及名为 Any 的能够适用于所有类型(即作为赋值的来源和目标)的特殊类型。

参见

PEP 471 - os.scandir() 函数 — 一个更好且更快的目录迭代器

PEP 471 [https://peps.python.org/pep-0471/] 向标准库添加了一个新的目录迭代函数 os.scandir()。 此外,os.walk() 现在是使用 scandir 来实现,这使它在 POSIX 系统上可提速 3 至 5 倍而在 Windows 系统上可提速 7 至 20 倍。 这样的效果主要是通过大幅减少遍历目录树所需调用 os.stat() 的次数来达成的。

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

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

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

参见

PEP 475: 重试返回 EINTR 失败码的系统调用

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

  • 忽略 InterruptedError

  • 处理 InterruptedError 并在每个调用位置尝试重新启动被中断的系统调用。

第一个选项会使应用程序中途出错。 第二个选项添加了大量的额外处理使得代码几乎不可读。 比较:

  1. print("Hello World")

和:

  1. while True:
  2. try:
  3. print("Hello World")
  4. break
  5. except InterruptedError:
  6. continue

PEP 475 [https://peps.python.org/pep-0475/] 实现了在 EINTR 时自动重试系统调用。 这移除了大部分场合下在用户代码中处理 EINTRInterruptedError 的负担,并使得 Python 程序,包括标准库的程序更为健壮。 请注意只有在信号处理器未引发异常时系统调用才会被重试。

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

参见

  • PEP 475 [https://peps.python.org/pep-0475/] — 重试返回 EINTR 失败码的系统调用
  • PEP 和具体实现由 Charles-François Natali 和 Victor Stinner 撰写,并获得 Antoine Pitrou 的协助(同为法国人)。

PEP 479:更改生成器内部的 StopIteration 处理

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

PEP 479 [https://peps.python.org/pep-0479/] 更改了生成器的行为:当一个 StopIteration 异常在生成器内部被引发时,它会在其退出生成器所在帧时被替换为 RuntimeError。 这一更改的主要目的是方便在无防护的 next() 调用引发了 StopIteration 并导致生成器所控制的迭代静默地终结的情况下进行调试。 此情况在与 yield from 构造相结合时会特别令人困扰。

这是一个向下不兼容的更改,所以想要启用这个新行为,必须执行 future 导入:

  1. >>> from __future__ import generator_stop
  2.  
  3. >>> def gen():
  4. ... next(iter([]))
  5. ... yield
  6. ...
  7. >>> next(gen())
  8. Traceback (most recent call last):
  9. File "<stdin>", line 2, in gen
  10. StopIteration
  11.  
  12. 上述异常是导致以下异常的直接原因:
  13.  
  14. Traceback (most recent call last):
  15. File "<stdin>", line 1, in <module>
  16. RuntimeError: generator raised StopIteration

如果未执行 __future__ 导入,当在生成器内部引发 StopIteration 异常时将导致 PendingDeprecationWarning 被引发。

参见

  • PEP 479 [https://peps.python.org/pep-0479/] — 更改生成器内部的 StopIteration 处理
  • PEP 由 Chris Angelico 和 Guido van Rossum 撰写,由 Chris Angelico,Yury Selivanov 和 Nick Coghlan 实现。

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

PEP 485 [https://peps.python.org/pep-0485/] 增加了 math.isclose()cmath.isclose() 函数用于检测两个值是否近似相等或称“接近”。 两个值是否接近是根据给定的绝对和相对范围来确定的。 相对范围是 isclose 参数之间的最大允许差值,即相对于较大的那个绝对数值的距离:

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

也可以使用绝对范围来比较两个值,它必须是一个非负数值:

  1. >>> import math
  2. >>> a = 5.0
  3. >>> b = 4.99998
  4. >>> math.isclose(a, b, abs_tol=0.00003)
  5. True
  6. >>> math.isclose(a, b, abs_tol=0.00001)
  7. False

参见

PEP 486:让 Python 启动器识别虚拟环境

PEP 486 [https://peps.python.org/pep-0486/] 让 Windows 版启动器 (参见 PEP 397 [https://peps.python.org/pep-0397/]) 能够识别激活的虚拟环境。 当要使用默认解释器并且设置了 VIRTUAL_ENV 环境变量时,将使用虚拟环境中的解释器。

参见

PEP 488:去除 PYO 文件

PEP 488 [https://peps.python.org/pep-0488/] 取消了 .pyo 文件的概念。 这意味着 .pyc 文件将同时代表未优化和已优化的字节码。 为了防止经常需要重新生成字节码文件,现在 .pyc 文件可以在其名称中设置可选的 opt- 标签来表示已优化字节码。 该设置的附带效果是当以 -O-OO 运行时将不会有字节码文件名冲突。 其结果是,使用 -O-OO 生成的字节码现在可以同时存在。 importlib.util.cache_from_source() 专门针对此项变化更新了 API。

参见

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

PEP 489 [https://peps.python.org/pep-0489/] 更新了扩展模块初始化操作以便利用 Python 3.4 中通过 PEP 451 [https://peps.python.org/pep-0451/] 引入的两步模块加载机制的优势。

这一变化让选择使用新机制的扩展模块的导入语义与 Python 源代码和字节码模块的更为接近,包括可以使用任何有效标识符作为模块名称,而不是仅限于 ASCII。

参见

其他语言特性修改

对Python 语言核心进行的小改动:

新增模块

typing

新增的 typing 暂定 模块提供了对函数类型标注的标准定义和工具。 详情参见 类型提示

zipapp

新增的 zipapp 模块(在 PEP 441 [https://peps.python.org/pep-0441/] 中描述)提供了用于创建可执行 Python Zip 应用程序的 API 和命令行工具,它是根据 bpo-1739468 [https://bugs.python.org/issue?@action=redirect&bpo=1739468] 在 Python 2.6 中引入的,但在当时和之后都没有足够的推广。

使用这个新模块,想要打包你的应用程序只需简单地将所有文件,包括一个 __main__.py 文件放到一个目录 myapp 中并运行:

  1. $ python -m zipapp myapp
  2. $ python myapp.pyz

该模块的实现由 Paul Moore 在 bpo-23491 [https://bugs.python.org/issue?@action=redirect&bpo=23491] 中贡献。

参见

PEP 441 [https://peps.python.org/pep-0441/] — 改进 Python ZIP 应用程序支持

改进的模块

argparse

现在 ArgumentParser 类允许通过将 allow_abbrev 设为 False 来禁用长选项的 缩写用法。 (由 Jonathan Paugh, Steven Bethard, paul j3 和 Daniel Eriksson 在 bpo-14910 [https://bugs.python.org/issue?@action=redirect&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 [https://bugs.python.org/issue?@action=redirect&bpo=15955] 中贡献。)

cgi

现在 FieldStorage 类已支持 context manager 协议。 (由 Berker Peksag 在 bpo-20289 [https://bugs.python.org/issue?@action=redirect&bpo=20289] 中贡献。)

cmath

新增函数 isclose() 提供了一种测试近似相等的方式。 (由 Chris Barker 和 Tal Einat 在 bpo-24270 [https://bugs.python.org/issue?@action=redirect&bpo=24270] 中贡献。)

code

现在 InteractiveInterpreter.showtraceback() 方法将打印完整的回溯链,就像在交互模式解释器中一样。 (由 Claudiu Popa 在 bpo-17442 [https://bugs.python.org/issue?@action=redirect&bpo=17442] 中贡献。)

collections

现在 OrderedDict 类使用 C 来实现,令其可提速 4 至 100 倍。 (由 Eric Snow 在 bpo-16991 [https://bugs.python.org/issue?@action=redirect&bpo=16991] 中贡献。)

OrderedDict.items(), OrderedDict.keys(), OrderedDict.values() 等视图现在支持 reversed() 迭代。 (由 Serhiy Storchaka 在 bpo-19505 [https://bugs.python.org/issue?@action=redirect&bpo=19505] 中贡献。)

deque 类现在定义了 index(), insert()copy(),并且支持 +* 运算符。 这允许 deque 被识别为 MutableSequence 并提升其替代列表的能力。 (由 Raymond Hettinger 在 bpo-23704 [https://bugs.python.org/issue?@action=redirect&bpo=23704] 中贡献。)

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

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

(由 Berker Peksag 在 bpo-24064 [https://bugs.python.org/issue?@action=redirect&bpo=24064] 中贡献。)

现在 UserString 类已实现 __getnewargs__(), __rmod__(), casefold(), format_map(), isprintable()maketrans() 类以与对应的 str 方法相匹配。 (由 Joe Jevnik 在 bpo-22189 [https://bugs.python.org/issue?@action=redirect&bpo=22189] 中贡献。)

collections.abc

现在 Sequence.index() 方法接受 startstop 参数以与对应的 tuple, list 等的方法相匹配。 (由 Devin Jeanpierre 在 bpo-23086 [https://bugs.python.org/issue?@action=redirect&bpo=23086] 中贡献。)

新增 Generator 抽象基类。 (由 Stefan Behnel 在 bpo-24018 [https://bugs.python.org/issue?@action=redirect&bpo=24018] 中贡献。)

新增 Awaitable, Coroutine, AsyncIteratorAsyncIterable 抽象基类。 (由 Yury Selivanov 在 bpo-24184 [https://bugs.python.org/issue?@action=redirect&bpo=24184] 中贡献。)

对于更早的 Python 版本,这些新 ABC 的向下移植版本包含在外部的 PyPI 软件包 [https://pypi.org/project/backports_abc/] 之中。

compileall

新增 compileall 选项 -j N,允许同时运行 N 个工作进程来执行并行的字节码编译。 compile_dir() 函数增加了相应的 workers 形参。 (由 Claudiu Popa 在 bpo-16104 [https://bugs.python.org/issue?@action=redirect&bpo=16104] 中贡献。)

另一个新选项 -r,允许控制最大的子目录递归层级。 (由 Claudiu Popa 在 bpo-19628 [https://bugs.python.org/issue?@action=redirect&bpo=19628] 中贡献。)

现在可以多次指定 -q 命令行选项,在此情况下,所有输出包括错误都将被抑制。 在 compile_dir(), compile_file()compile_path() 中相应的 quiet 形参现在可接受一个整数值来指明输出抑制的级别。 (由 Thomas Kluyver 在 bpo-21338 [https://bugs.python.org/issue?@action=redirect&bpo=21338] 中贡献。)

concurrent.futures

现在 Executor.map() 方法接受一个 chunksize 参数以允许在使用 ProcessPoolExecutor() 设置任务批次来提升运行效率。 (由 Dan O'Reilly 在 bpo-11271 [https://bugs.python.org/issue?@action=redirect&bpo=11271] 中贡献。)

现在 ThreadPoolExecutor 构造器中的工作线程数量是可选的。 默认值为 CPU 数量的 5 倍。 (由 Claudiu Popa 在 bpo-21527 [https://bugs.python.org/issue?@action=redirect&bpo=21527] 中贡献。)

configparser

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

示例:

  1. >>> import configparser
  2. >>> conv = {}
  3. >>> conv['list'] = lambda v: [e.strip() for e in v.split() if e.strip()]
  4. >>> cfg = configparser.ConfigParser(converters=conv)
  5. >>> cfg.read_string("""
  6. ... [s]
  7. ... list = a b c d e f g
  8. ... """)
  9. >>> cfg.get('s', 'list')
  10. 'a b c d e f g'
  11. >>> cfg.getlist('s', 'list')
  12. ['a', 'b', 'c', 'd', 'e', 'f', 'g']
  13. >>> section = cfg['s']
  14. >>> section.getlist('list')
  15. ['a', 'b', 'c', 'd', 'e', 'f', 'g']

(由 Łukasz Langa 在 bpo-18159 [https://bugs.python.org/issue?@action=redirect&bpo=18159] 中贡献。)

contextlib

新增的 redirect_stderr() context manager (类似于 redirect_stdout()) 使得工具脚本更容易处理那些将输出写入到 sys.stderr 并且不提供任何重定向选项的不灵活 API。

  1. >>> import contextlib, io, logging
  2. >>> f = io.StringIO()
  3. >>> with contextlib.redirect_stderr(f):
  4. ... logging.warning('warning')
  5. ...
  6. >>> f.getvalue()
  7. 'WARNING:root:warning\n'

(由 Berker Peksag 在 bpo-22389 [https://bugs.python.org/issue?@action=redirect&bpo=22389] 中贡献。)

csv

现在 writerow() 方法可支持任意可迭代对象,而不仅是序列。 (由 Serhiy Storchaka 在 bpo-23171 [https://bugs.python.org/issue?@action=redirect&bpo=23171] 中贡献。)

curses

新增的 update_lines_cols() 函数可更新 LINESCOLS 模块变量。 这适用于检测手册页屏幕的大小变化。 (由 Arnon Yaari 在 bpo-4254 [https://bugs.python.org/issue?@action=redirect&bpo=4254] 中贡献。)

dbm

当设置旗标值为 "n"dumb.open 将总是创建新的数据库。 (由 Claudiu Popa 在 bpo-18039 [https://bugs.python.org/issue?@action=redirect&bpo=18039] 中贡献。)

difflib

HtmlDiff.make_file() 生成的 HTML 文档的字符集现在可通过使用新增的 charset 仅限关键字参数来自定义。 HTML 文档的默认字符集已从 "ISO-8859-1" 改为 "utf-8"。 (由 Berker Peksag 在 bpo-2052 [https://bugs.python.org/issue?@action=redirect&bpo=2052] 中贡献。)

现在 diff_bytes() 函数可能比较字节串的列表。 这修复了一个来自 Python 2 遗留总是。 (由 Terry J. Reedy 和 Greg Ward 在 bpo-17445 [https://bugs.python.org/issue?@action=redirect&bpo=17445] 中贡献。)

distutils

现在 buildbuild_ext 命令都接受一个 -j 选项以启用扩展模块的并行编译。 (由 Antoine Pitrou 在 bpo-5309 [https://bugs.python.org/issue?@action=redirect&bpo=5309] 中贡献。)

现在 distutils 模块支持 xz 压缩,并可通过将 xztar 作为传给 bdist --format 的参数来启用。 (由 Serhiy Storchaka 在 bpo-16314 [https://bugs.python.org/issue?@action=redirect&bpo=16314] 中贡献。)

doctest

如果 module 不包含任何文档字符串则 DocTestSuite() 函数将返回一个空的 unittest.TestSuite,而不是引发 ValueError。 (由 Glenn Jones 在 bpo-15916 [https://bugs.python.org/issue?@action=redirect&bpo=15916] 中贡献。)

email

新增的策略选项 Policy.mangle_from_ 可控制生成器是否要为电子邮件消息体中以controls whether or not lines that start with "From " 打头的行添加 ">" 字符前缀。 默认 compat32True 而所有其他策略均为 False。 (由 Milan Oberkirch 在 bpo-20098 [https://bugs.python.org/issue?@action=redirect&bpo=20098] 中贡献。)

新增的 Message.get_content_disposition() 方法可提供对 Content-Disposition 标头规范值的便捷访问。 (由 Abhilash Raj 在 bpo-21083 [https://bugs.python.org/issue?@action=redirect&bpo=21083] 中贡献。)

新增的策略选项 EmailPolicy.utf8 可被设为 True 以使用 UTF-8 字符集而不是使用已编码的字来编码电子邮件标头。 这将允许根据 RFC 6532 [https://datatracker.ietf.org/doc/html/rfc6532.html] 来格式化 Messages 并配合支持 RFC 6531 [https://datatracker.ietf.org/doc/html/rfc6531.html] SMTPUTF8 扩展的 SMTP 服务器使用。 (由 R. David Murray 在 bpo-24211 [https://bugs.python.org/issue?@action=redirect&bpo=24211] 中贡献。)

现在 mime.text.MIMEText 构造器可接受一个 charset.Charset 实例。 (由 Claude Paroz 和 Berker Peksag 在 bpo-16324 [https://bugs.python.org/issue?@action=redirect&bpo=16324] 中贡献。)

enum

Enum 可调用对象新增了一个形参 start 用于在只提供了 names 的情况下指定枚举值的初始数量:

  1. >>> Animal = enum.Enum('Animal', 'cat dog', start=10)
  2. >>> Animal.cat
  3. <Animal.cat: 10>
  4. >>> Animal.dog
  5. <Animal.dog: 11>

(由 Ethan Furman 在 bpo-21706 [https://bugs.python.org/issue?@action=redirect&bpo=21706] 中贡献。)

faulthandler

现在 enable(), register(), dump_traceback()dump_traceback_later() 函数除了接受文件型对象以外也接受文件描述符。 (由 Wei Wu 在 bpo-23566 [https://bugs.python.org/issue?@action=redirect&bpo=23566] 中贡献。)

functools

现在大部分 lru_cache() 机制已使用 C 实现,使其速度显著提升。 (由 Matt Joiner, Alexey Kachayev 和 Serhiy Storchaka 在 bpo-14373 [https://bugs.python.org/issue?@action=redirect&bpo=14373] 中贡献。)

glob

现在 iglob()glob() 函数支持通过使用 "**" 模式在子目录中递归搜索。 (由 Serhiy Storchaka 在 bpo-13968 [https://bugs.python.org/issue?@action=redirect&bpo=13968] 中贡献。)

gzip

现在 GzipFile 构造器的 mode 参数可接受 "x" 来请求独占式的创建。 (由 Tim Heaney 在 bpo-19222 [https://bugs.python.org/issue?@action=redirect&bpo=19222] 中贡献。)

heapq

现在 merge() 中的元素比较可通过在新增的可选关键字参数 key 中传入一个 key function 来进行定制,并且新增了可选关键字参数 reverse 用于反向的元素比较:

  1. >>> import heapq
  2. >>> a = ['9', '777', '55555']
  3. >>> b = ['88', '6666']
  4. >>> list(heapq.merge(a, b, key=len))
  5. ['9', '88', '777', '6666', '55555']
  6. >>> list(heapq.merge(reversed(a), reversed(b), key=len, reverse=True))
  7. ['55555', '6666', '777', '88', '9']

(由 Raymond Hettinger 在 bpo-13742 [https://bugs.python.org/issue?@action=redirect&bpo=13742] 中贡献。)

http

新增的 HTTPStatus 枚举定义了一组 HTTP 状态码、英文短说明和长描述。 (由 Demian Brecht 在 bpo-21793 [https://bugs.python.org/issue?@action=redirect&bpo=21793] 中贡献。)

http.client

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

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

(由 Martin Panter 在 bpo-3566 [https://bugs.python.org/issue?@action=redirect&bpo=3566] 中贡献。)

idlelib 与 IDLE

由于 idlelib 实现了 IDLE 命令行界面和编辑器且不应被其他程序导入,它将随每个发布版获得不断改进。 请参阅 Lib/idlelib/NEWS.txt 查看 3.4.0 以来的累积改变列表,以及未来 3.5.x 发布版将进行的改变。 此文件也可通过 IDLE Help ‣ About IDLE 对话框查看。

imaplib

现在 IMAP4 类已支持 context manager 协议。 当用于 with 语句时,IMAP4 LOGOUT 命令将在代码块的末尾被自动调用。 (由 Tarek Ziadé 和 Serhiy Storchaka 在 bpo-4972 [https://bugs.python.org/issue?@action=redirect&bpo=4972] 中贡献。)

现在 imaplib 模块已通过 IMAP4.enable() 方法支持 RFC 5161 [https://datatracker.ietf.org/doc/html/rfc5161.html] (ENABLE 扩展) 和 RFC 6855 [https://datatracker.ietf.org/doc/html/rfc6855.html] (UTF-8 支持)。 新增的 IMAP4.utf8_enabled 属性可跟踪 RFC 6855 [https://datatracker.ietf.org/doc/html/rfc6855.html] 支持是否被启用。 (由 Milan Oberkirch, R. David Murray 和 Maciej Szulik 在 bpo-21800 [https://bugs.python.org/issue?@action=redirect&bpo=21800] 中贡献。)

现在 imaplib 模块会自动使用 UTF-8 自动编码非 ASCII 字符串的用户名和密码,如 RFC 所建议的那样。 (由 Milan Oberkirch 在 bpo-21800 [https://bugs.python.org/issue?@action=redirect&bpo=21800] 中贡献。)

imghdr

现在 what() 函数可识别 OpenEXR [https://www.openexr.com] 格式(由 Martin Vignali 和 Claudiu Popa 在 bpo-20295 [https://bugs.python.org/issue?@action=redirect&bpo=20295] 中贡献),以及 WebP [https://en.wikipedia.org/wiki/WebP] 格式(由 Fabrice Aneche 和 Claudiu Popa 在 bpo-20197 [https://bugs.python.org/issue?@action=redirect&bpo=20197] 中贡献。)

importlib

util.LazyLoader 类允许在对启动时间敏感的应用程序中使用模块的惰性加载。 (由 Brett Cannon 在 bpo-17621 [https://bugs.python.org/issue?@action=redirect&bpo=17621] 中贡献。)

现在 abc.InspectLoader.source_to_code() 方法属于静态方法。 这样将可更方便地通过运行 exec(code, module.__dict__) 基于字符串编译的代码来初始化模块。 (由 Brett Cannon 在 bpo-21156 [https://bugs.python.org/issue?@action=redirect&bpo=21156] 中贡献。)

新增的 util.module_from_spec() 函数现在是创建新模块的首先方式。 相比直接创建 types.ModuleType 实例,这个新函数将基于传入的规格说明对象设置各种导入控制的属性。 (由 Brett Cannon 在 bpo-20383 [https://bugs.python.org/issue?@action=redirect&bpo=20383] 中贡献。)

inspect

现在 SignatureParameter 类都是可封存和可哈希的对象。 (由 Yury Selivanov 在 bpo-20726 [https://bugs.python.org/issue?@action=redirect&bpo=20726] 和 bpo-20334 [https://bugs.python.org/issue?@action=redirect&bpo=20334] 中贡献。)

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

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

(由 Yury Selivanov 在 bpo-24190 [https://bugs.python.org/issue?@action=redirect&bpo=24190] 中贡献。)

新增的类方法 Signature.from_callable() 使得 Signature 的子类化更为容易。 (由 Yury Selivanov 和 Eric Snow 在 bpo-17373 [https://bugs.python.org/issue?@action=redirect&bpo=17373] 中贡献。)

现在 signature() 函数接受 followwrapped 可选关键字参数,当其设为 False 时,将禁用 \_wrapped__ 链接的自动跟随。 (由 Yury Selivanov 在 bpo-20691 [https://bugs.python.org/issue?@action=redirect&bpo=20691] 中贡献。)

新增了一组用于检查 协程函数协程对象 的函数: iscoroutine(), iscoroutinefunction(), isawaitable(), getcoroutinelocals()getcoroutinestate()。 (由 Yury Selivanov 在 bpo-24017 [https://bugs.python.org/issue?@action=redirect&bpo=24017] 和 bpo-24400 [https://bugs.python.org/issue?@action=redirect&bpo=24400] 中贡献。)

现在 stack(), trace(), getouterframes()getinnerframes() 函数将返回具名元组的列表。 (由 Daniel Shahaf 在 bpo-16808 [https://bugs.python.org/issue?@action=redirect&bpo=16808] 中贡献。)

io

新增 BufferedIOBase.readinto1() 方法,该方法会使用至少一次对下层原始流的调用 RawIOBase.read()RawIOBase.readinto() 方法。 (由 Nikolaus Rath 在 bpo-20578 [https://bugs.python.org/issue?@action=redirect&bpo=20578] 中贡献。)

ipaddress

现在 IPv4NetworkIPv6Network 类均接受一个 (address, netmask) 元组参数,可以根据现有地址方便地构造网络对象:

  1. >>> import ipaddress
  2. >>> ipaddress.IPv4Network(('127.0.0.0', 8))
  3. IPv4Network('127.0.0.0/8')
  4. >>> ipaddress.IPv4Network(('127.0.0.0', '255.0.0.0'))
  5. IPv4Network('127.0.0.0/8')

(由 Peter Moody 和 Antoine Pitrou 在 bpo-16531 [https://bugs.python.org/issue?@action=redirect&bpo=16531] 中贡献。)

新增 IPv4NetworkIPv6Network 类的 reverse_pointer 属性用于返回 DNS PTR 反向记录的名称:

  1. >>> import ipaddress
  2. >>> addr = ipaddress.IPv4Address('127.0.0.1')
  3. >>> addr.reverse_pointer
  4. '1.0.0.127.in-addr.arpa'
  5. >>> addr6 = ipaddress.IPv6Address('::1')
  6. >>> addr6.reverse_pointer
  7. '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 [https://bugs.python.org/issue?@action=redirect&bpo=20480] 中贡献。)

json

现在 json.tool 命令行接口会保留输入中传入的 JSON 对象中键的顺序。 新的 --sort-keys 选项可用于按字母顺序对键进行排序。 (由 Berker Peksag 在 bpo-21650 [https://bugs.python.org/issue?@action=redirect&bpo=21650] 中贡献。)

现在 JSON 解码器会引发 JSONDecodeError 而不是 ValueError 以提供有关错误的更好的上下文信息。 (由 Serhiy Storchaka 在 bpo-19361 [https://bugs.python.org/issue?@action=redirect&bpo=19361] 中贡献。)

linecache

新增的 lazycache() 函数可用于捕获非基于文件的模块 的信息以允许在此后通过 getline() 获取其行数据。 这样就可以避免在实际需要某一行之前执行 I/O 操作,从而不需要无限期地持有模块 globals。 (由 Robert Collins 在 bpo-17911 [https://bugs.python.org/issue?@action=redirect&bpo=17911] 中贡献。)

locale

新增的 delocalize() 函数可用于将字符串转换为表示规范化数字的字符串 ,并会考虑 LC_NUMERIC 的设置:

  1. >>> import locale
  2. >>> locale.setlocale(locale.LC_NUMERIC, 'de_DE.UTF-8')
  3. 'de_DE.UTF-8'
  4. >>> locale.delocalize('1.234,56')
  5. '1234.56'
  6. >>> locale.setlocale(locale.LC_NUMERIC, 'en_US.UTF-8')
  7. 'en_US.UTF-8'
  8. >>> locale.delocalize('1,234.56')
  9. '1234.56'

(由 Cédric Krier 在 bpo-13918 [https://bugs.python.org/issue?@action=redirect&bpo=13918] 中贡献。)