Python 3.5 的新特性 — Python 文档
Python 3.5 中的新功能
- 编辑
- 埃尔维斯·普兰斯克维奇 < 猫王@magic.io >, 尤里·塞利瓦诺夫 < yury@magic.io >
本文解释了 Python 3.5 中与 3.4 相比的新特性。 Python 3.5 于 2015 年 9 月 13 日发布。 请参阅 changelog 以获取完整的更改列表。
摘要 – 发布亮点
新的语法特性:
新的库模块:
新的内置功能:
bytes % args
,bytearray % args
: PEP 461 – 将%
格式添加到字节和字节数组。- 新的 bytes.hex()、bytearray.hex() 和 memoryview.hex() 方法。 (由 Arnon Yaari 在 :issue:`9951` 中贡献。)
- memoryview 现在支持元组索引(包括多维)。 (由 Antoine Pitrou 在 中提供:issue:`23632`。)
- 生成器有一个新的
gi_yieldfrom
属性,它返回由yield from
表达式迭代的对象。 (由 Benno Leslie 和 Yury Selivanov 在 中提供:issue:`24450`。) - 当达到最大递归深度时,现在会引发新的 RecursionError 异常。 (由 Georg Brandl 在 中提供:issue:`19235`。)
CPython 实现改进:
- 当
LC_TYPE
语言环境是 POSIX 语言环境(C
语言环境)时,sys.stdin 和 sys.stdout 现在使用surrogateescape
] 错误处理程序,而不是strict
错误处理程序。 (由 Victor Stinner 在 :issue:`19977` 中提供。) .pyo
文件不再使用,取而代之的是更灵活的方案,该方案在.pyc
名称中明确包含优化级别。 (请参阅 PEP 488 概述 。)- 内置和扩展模块现在在多阶段过程中初始化,这类似于 Python 模块的加载方式。 (请参阅 PEP 489 概述 。)
标准库的重大改进:
- collections.OrderedDict 现在在 C 中实现了 ,使其速度提高了 4 到 100 倍。
- ssl 模块获得了对 Memory BIO 的 支持,它将 SSL 协议处理与网络 IO 分离。
- 新的 os.scandir() 函数提供了 更好、更快的目录遍历方式 。
- functools.lru_cache() 大部分 在 C 中重新实现,产生更好的性能。
- 新的 subprocess.run() 函数提供了一种 简化的方式来运行子进程 。
- traceback 模块已显着 增强 ,以提高性能和开发人员的便利性。
安全改进:
- SSLv3 现在在整个标准库中都被禁用。 它仍然可以通过手动实例化 ssl.SSLContext 来启用。 (有关更多详细信息,请参阅 :issue:`22638`;此更改已向后移植到 CPython 3.4 和 2.7。)
- HTTP cookie 解析现在更加严格,以防止潜在的注入攻击。 (由 Antoine Pitrou 在 中提供:issue:`22796`。)
Windows 改进:
- 一个新的 Windows 安装程序取代了旧的 MSI。 有关更多信息,请参阅 在 Windows 上使用 Python 。
- Windows 版本现在使用 Microsoft Visual C++ 14.0,并且扩展模块应该使用相同的。
请继续阅读以获取面向用户的更改的完整列表,包括许多其他较小的改进、CPython 优化、弃用和潜在的移植问题。
新特性
PEP 492 - 带有 async 和 await 语法的协程
PEP 492通过添加awaitable对象、协程函数、异步迭代大大提高了对Python异步编程的支持, 和 异步上下文管理器 。
协程函数使用新的 async def 语法声明:
>>> async def coro():
... return 'spam'
在协程函数中,新的 await 表达式可用于暂停协程执行,直到结果可用。 任何对象都可以是 awaited,只要它通过定义 __await__()
方法实现了 awaitable 协议。
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 for 和 async with 只能在用 async def 声明的协程函数中使用。
协程函数旨在在兼容的事件循环中运行,例如 asyncio 循环 。
笔记
3.5.2版本变更:从CPython 3.5.2开始,__aiter__
可以直接返回异步迭代器。 返回 awaitable 对象将导致 PendingDeprecationWarning。
在 异步迭代器 文档部分查看更多详细信息。
PEP 465 - 用于矩阵乘法的专用中缀运算符
PEP 465 为矩阵乘法添加了 @
中缀运算符。 目前,没有内置的 Python 类型实现 new 运算符,但是,可以通过为常规矩阵、反射矩阵和原位矩阵定义 __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 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 461 - 字节和字节数组的百分比格式支持
PEP 461 添加了对 %
插值运算符 到 bytes 和 bytearray 的支持。
虽然插值通常被认为是一种字符串操作,但在某些情况下,bytes
或 bytearrays
上的插值是有意义的,而弥补这一缺失功能所需的工作会降低整体可读性编码。 这个问题在处理有线格式协议时尤为重要,这些协议通常是二进制和 ASCII 兼容文本的混合体。
例子:
>>> b'Hello %b!' % b'World'
b'Hello World!'
>>> b'x=%i y=%f' % (1, 2.5)
b'x=1 y=2.500000'
%b
不允许使用 Unicode,但 %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 484 - 类型提示
自 3.0 版(PEP 3107)以来,函数注释语法一直是 Python 的一个特性,但是注释的语义尚未定义。
经验表明,大多数函数注释的用途是为函数参数和返回值提供类型提示。 很明显,如果标准库包含用于类型注释的基本定义和工具,这对 Python 用户将是有益的。
PEP 484 引入了一个 临时模块 来提供这些标准定义和工具,以及一些用于注释不可用情况的约定。
例如,这是一个简单的函数,其参数和返回类型在注释中声明:
def greeting(name: str) -> str:
return 'Hello ' + name
虽然这些注释在运行时通过通常的 __annotations__
属性可用,但 在运行时没有自动类型检查 。 相反,假设有一个单独的离线类型检查器(例如 mypy) 将用于按需源代码分析。
类型系统支持联合、泛型和一个名为 Any 的特殊类型,它与(即 可分配给和来自)所有类型。
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 475:使用 EINTR 重试失败的系统调用
每当等待 I/O 的系统调用被信号中断时,就会返回 errno.EINTR 错误代码。 以前,在这种情况下,Python 会引发 InterruptedError。 这意味着,在编写 Python 应用程序时,开发人员有两种选择:
- 忽略
InterruptedError
。 - 处理
InterruptedError
并尝试在每个调用点重新启动中断的系统调用。
第一个选项使应用程序间歇性失败。 第二个选项添加了大量样板文件,使代码几乎不可读。 相比:
print("Hello World")
和:
while True:
try:
print("Hello World")
break
except InterruptedError:
continue
PEP 475 在 EINTR
上实现了系统调用的自动重试。 这消除了在大多数情况下处理用户代码中的 EINTR
或 InterruptedError 的负担,并使 Python 程序(包括标准库)更加健壮。 请注意,只有在信号处理程序未引发异常时才会重试系统调用。
下面是在被信号中断时重试的函数列表:
- open() 和 io.open();
- faulthandler 模块的功能;
- os 函数:fchdir()、fchmod()、fchown()、fdatasync()、 X102X]fstat()、fstatvfs()、fsync()、ftruncate()、mkfifo() X200X]mknod()、open()、posix_fadvise()、posix_fallocate()、、309]X X317X]pwrite()、read()、readv()、sendfile()、wait3()、[ X420X]wait4(), wait(), waitid(), waitpid(), write(), [ X522X]writev();
- 特殊情况:os.close() 和 os.dup2() 现在忽略 EINTR 错误; 系统调用不会重试(请参阅 PEP 了解基本原理);
- select 函数:devpoll.poll()、epoll.poll()、kqueue.control()、poll。投票(),选择();
- socket 类的方法:accept()、connect()(非阻塞套接字除外)、recv()、 recvfrom()、recvmsg()、send()、sendall()、sendmsg() sendto();
- signal.sigtimedwait() 和 signal.sigwaitinfo();
- time.sleep()。
也可以看看
- 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 486:让 Python Launcher 了解虚拟环境
PEP 486 使 Windows 启动器(参见 PEP 397)意识到活动的虚拟环境。 当将使用默认解释器并设置 VIRTUAL_ENV
环境变量时,将使用虚拟环境中的解释器。
其他语言更改
对核心 Python 语言进行的一些较小更改是:
- 添加了
"namereplace"
错误处理程序。"backslashreplace"
错误处理程序现在可用于解码和翻译。 (由 Serhiy Storchaka 在 :issue:`19676` 和 :issue:`22286` 中贡献。) - -b 选项现在影响 bytes 与 int 的比较。 (由 Serhiy Storchaka 在 中提供:issue:`23681`。)
- 新的哈萨克语
kz1048
和塔吉克语koi8_t
编解码器 。 (由 Serhiy Storchaka 在 :issue:`22682` 和 :issue:`22681` 中贡献。) - 属性文档字符串现在是可写的。 这对于 collections.namedtuple() 文档字符串特别有用。 (由 Berker Peksag 在 中提供:issue:`24064`。)
- 现在支持涉及相对导入的循环导入。 (由 Brett Cannon 和 Antoine Pitrou 在 :issue:`17636` 中提供。)
新模块
压缩包
新的 zipapp 模块(在 PEP 441 中指定)提供了用于创建可执行 Python Zip 应用程序的 API 和命令行工具,这些应用程序是在 Python 2.6 中引入的X198X]:issue:`1739468`,但在当时或之后都没有得到很好的宣传。
使用新模块,捆绑您的应用程序就像将所有文件(包括 __main__.py
文件)放入目录 myapp
并运行一样简单:
$ python -m zipapp myapp
$ python myapp.pyz
模块实现由 Paul Moore 在 :issue:`23491` 中贡献。
改进的模块
参数解析
ArgumentParser 类现在允许通过将 allow_abbrev 设置为 False
来禁用长选项的 缩写用法 。 (由 Jonathan Paugh、Steven Bethard、paul j3 和 Daniel Eriksson 在 :issue:`14910` 中提供。)
异步
由于 asyncio 模块是 临时 ,因此 Python 3.5 中引入的所有更改也已向后移植到 Python 3.4.x。
自 Python 3.4.0 以来 asyncio 模块的显着变化:
- 新的调试 API:loop.set_debug() 和 loop.get_debug() 方法。 (维克多·斯廷纳供稿。)
- proactor 事件循环现在支持 SSL。 (由 Antoine Pitrou 和 Victor Stinner 在 中提供:issue:`22560`。)
- 一个新的 loop.is_closed() 方法来检查事件循环是否关闭。 (由 Victor Stinner 在 中提供:问题:`21326`。)
- 一个新的 loop.create_task() 可以方便地为协程创建和安排一个新的 Task。
create_task
方法也被所有将协程包装成任务的 asyncio 函数使用,例如asyncio.wait()
、asyncio.gather()
等。 (维克多·斯廷纳供稿。) - 一个新的 transport.get_write_buffer_limits() 方法来查询流量控制的 high- 和 low- 水限制。 (维克多·斯廷纳供稿。)
async()
函数被弃用,取而代之的是 ensure_future()。 (由尤里·塞利瓦诺夫提供。)- 新的 loop.set_task_factory() 和 loop.get_task_factory() 方法来自定义 loop.create_task() 方法使用的任务工厂。 (由尤里·塞利瓦诺夫提供。)
- 新的
Queue.join()
和 Queue.task_done() 队列方法。 (维克多·斯廷纳供稿。) JoinableQueue
类被移除,取而代之的是 asyncio.Queue 类。 (维克多·斯廷纳供稿。)
3.5.1 中的更新:
- ensure_future() 函数和所有使用它的函数,例如 loop.run_until_complete(),现在接受各种 awaitable 对象 。 (由尤里·塞利瓦诺夫提供。)
- 新的 run_coroutine_threadsafe() 函数将协程提交给来自其他线程的事件循环。 (文森特·米歇尔供稿。)
- 新的 Transport.is_closure() 方法来检查传输是关闭还是关闭。 (由尤里·塞利瓦诺夫提供。)
loop.create_server()
方法现在可以接受主机列表。 (由 Yann Sionneau 提供。)
3.5.2 中的更新:
- 新的 loop.create_future() 方法来创建 Future 对象。 这允许替代事件循环实现,例如 uvloop,以提供更快的 asyncio.Future 实现。 (由尤里·塞利瓦诺夫提供。)
- 新的 loop.get_exception_handler() 方法来获取当前异常处理程序。 (由尤里·塞利瓦诺夫提供。)
- 新的
StreamReader.readuntil()
方法从流中读取数据,直到出现分隔符字节序列。 (马克·科伦伯格供稿。) - 优化了
loop.create_connection()
和loop.create_server()
方法,以避免在地址已经解析的情况下调用系统getaddrinfo
函数。 (由 A. 杰西·吉留·戴维斯。) loop.sock_connect(sock, address)
不再需要在调用之前解析 地址 。 (由 A. 杰西·吉留·戴维斯。)
bz2
BZ2Decompressor.decompress 方法现在接受一个可选的 max_length 参数来限制解压缩数据的最大大小。 (由 Nikolaus Rath 在 :issue:`15955` 中提供。)
收藏
OrderedDict 类现在是用 C 实现的,这使它快了 4 到 100 倍。 (由 Eric Snow 在 中贡献:问题:`16991`。)
OrderedDict.items()
、OrderedDict.keys()
、OrderedDict.values()
视图现在支持 reversed() 迭代。 (由 Serhiy Storchaka 在 :issue:`19505` 中提供。)
deque 类现在定义了 index()、insert() 和 copy(),并支持 +
] 和 *
运算符。 这允许双端队列被识别为 MutableSequence 并提高它们对列表的可替换性。 (由 Raymond Hettinger 在 中提供:issue:`23704`。)
namedtuple() 生成的文档字符串现在可以更新:
Point = namedtuple('Point', ['x', 'y'])
Point.__doc__ += ': Cartesian coodinate'
Point.x.__doc__ = 'abscissa'
Point.y.__doc__ = 'ordinate'
(由 Berker Peksag 在 中提供:issue:`24064`。)
UserString 类现在实现了 __getnewargs__()
、__rmod__()
、casefold()、format_map()、isprintable () 和 maketrans() 方法来匹配 str 的对应方法。 (由 Joe Jevnik 在 :issue:`22189` 中提供。)
收藏.abc
Sequence.index()
方法现在接受 start 和 stop 参数以匹配 tuple、list 等的相应方法。 (由 Devin Jeanpierre 在 中提供:issue:`23086`。)
一个新的 Generator 抽象基类。 (由 Stefan Behnel 在 :issue:`24018` 中贡献。)
新的 Awaitable、Coroutine、AsyncIterator 和 AsyncIterable 抽象基类。 (由 Yury Selivanov 在 中提供:issue:`24184`。)
对于较早的 Python 版本,新 ABC 的向后移植可在外部 PyPI 包 中获得。
编译所有
一个新的 compileall 选项,-j N
,允许同时运行 N 个工人来执行并行字节码编译。 compile_dir() 函数有一个对应的 workers
参数。 (由克劳迪乌·波帕在 中提供:issue:`16104`。)
另一个新选项 -r
允许控制子目录的最大递归级别。 (由克劳迪乌·波帕在 中提供:issue:`19628`。)
-q
命令行选项现在可以指定多次,在这种情况下,包括错误在内的所有输出都将被抑制。 compile_dir()、compile_file() 和 compile_path() 中相应的 quiet
参数现在可以接受一个整数值,表示级别输出抑制。 (由 Thomas Kluyver 在 :issue:`21338` 中贡献。)
并发期货
Executor.map() 方法现在接受 chunksize 参数,以在使用 ProcessPoolExecutor() 时允许批处理任务以提高性能。 (由 Dan O'Reilly 在 中提供:issue:`11271`。)
ThreadPoolExecutor 构造函数中的工作线程数量现在是可选的。 默认值为 CPU 数量的 5 倍。 (由 Claudiu Popa 在 中提供:issue:`21527`。)
配置解析器
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 在 中提供:issue:`18159`。)
上下文库
新的 redirect_stderr() 上下文管理器 (类似于 redirect_stdout())使实用程序脚本更容易处理将其输出写入 的不灵活的 API sys.stderr 并且不提供任何重定向它的选项:
>>> import contextlib, io, logging
>>> f = io.StringIO()
>>> with contextlib.redirect_stderr(f):
... logging.warning('warning')
...
>>> f.getvalue()
'WARNING:root:warning\n'
(由 Berker Peksag 在 中提供:issue:`22389`。)
诅咒
新的 update_lines_cols() 函数更新了 LINES
和 COLS
环境变量。 这对于检测手动调整屏幕大小很有用。 (由 Arnon Yaari 在 :issue:`4254` 中提供。)
差异库
HtmlDiff.make_file() 生成的 HTML 文档的字符集现在可以使用新的 charset 关键字参数进行自定义。 HTML 文档的默认字符集由 "ISO-8859-1"
更改为 "utf-8"
。 (由 Berker Peksag 在 :issue:`2052` 中提供。)
diff_bytes() 函数现在可以比较字节字符串列表。 这修复了 Python 2 的回归。 (由特里 J。 中的 Reedy 和 Greg Ward:问题:`17445`。)
分配器
build
和 build_ext
命令现在都接受 -j
选项以启用扩展模块的并行构建。 (由 Antoine Pitrou 在 中提供:issue:`5309`。)
distutils 模块现在支持 xz
压缩,并且可以通过将 xztar
作为参数传递给 bdist --format
来启用。 (由 Serhiy Storchaka 在 中提供:issue:`16314`。)
文档测试
DocTestSuite() 函数返回一个空的 unittest.TestSuite 如果 module 不包含文档字符串,而不是引发 ValueError。 (由 Glenn Jones 在 :issue:`15916` 中提供。)
电子邮件
新的策略选项 Policy.mangle_from_ 控制电子邮件正文中以 "From "
开头的行是否由生成器以 ">"
字符作为前缀。 compat32 的默认值为 True
,所有其他策略的默认值为 False
。 (由 Milan Oberkirch 在 :issue:`20098` 中提供。)
新的 Message.get_content_disposition() 方法可以轻松访问 Content-Disposition 标头的规范值。 (由 Abhilash Raj 在 中贡献:问题:`21083`。)
新的策略选项 EmailPolicy.utf8 可以设置为 True
以使用 UTF-8 字符集而不是使用编码字对电子邮件标头进行编码。 这允许 Messages
根据 RFC 6532 进行格式化,并与支持 RFC 6531 的 SMTP 服务器一起使用SMTPUTF8
扩展。 (由 R. 中的 David Murray:问题:`24211`。)
mime.text.MIMEText 构造函数现在接受一个 charset.Charset 实例。 (由 Claude Paroz 和 Berker Peksag 在 :issue:`16324` 中提供。)
枚举
如果仅提供 names,则 Enum 可调用有一个新参数 start 来指定枚举值的初始数量:
>>> Animal = enum.Enum('Animal', 'cat dog', start=10)
>>> Animal.cat
<Animal.cat: 10>
>>> Animal.dog
<Animal.dog: 11>
(由 Ethan Furman 在 中提供:问题:`21706`。)
故障处理程序
enable()、register()、dump_traceback() 和 dump_traceback_later() 函数现在除了文件之外还接受文件描述符像物体。 (由 Wei Wu 在 中提供:issue:`23566`。)
功能工具
大多数 lru_cache() 机制现在是用 C 实现的,使其速度明显加快。 (由 Matt Joiner、Alexey Kachayev 和 Serhiy Storchaka 在 :issue:`14373` 中提供。)
堆
merge() 中的元素比较现在可以通过在新的可选 key 关键字参数中传递 键函数 和新的可选 reverse[ X175X] 关键字参数可用于反向元素比较:
>>> 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 在 中提供:issue:`13742`。)
客户端
HTTPConnection.getresponse() 现在在远程服务器连接意外关闭时引发 RemoteDisconnected 异常。 此外,如果引发 ConnectionError(其中 RemoteDisconnected
是一个子类),则客户端套接字现在会自动关闭,并将在下一个请求时重新连接:
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 在 :issue:`3566` 中提供。)
空闲库和空闲
由于 idlelib 实现了 IDLE shell 和编辑器,并且不打算由其他程序导入,因此每个版本都会对其进行改进。 请参阅 Lib/idlelib/NEWS.txt
以获取自 3.4.0 以来的累积更改列表,以及在未来 3.5.x 版本中所做的更改。 该文件也可从 IDLE 对话框中获得。
映射库
IMAP4 类现在支持 上下文管理器 协议。 当在 with 语句中使用时,IMAP4 LOGOUT
命令将在块的末尾自动调用。 (由 Tarek Ziadé 和 Serhiy Storchaka 在 :issue:`4972` 中提供。)
imaplib 模块现在支持 RFC 5161(启用扩展)和 RFC 6855(UTF-8 支持)通过 IMAP4.enable() 方法。 新的 IMAP4.utf8_enabled 属性跟踪是否启用了 RFC 6855 支持。 (米兰奥伯基希供稿,R. :issue:`21800` 中的 David Murray 和 Maciej Szulik。)
imaplib 模块现在按照 RFC 的建议使用 UTF-8 自动编码非 ASCII 字符串用户名和密码。 (由 Milan Oberkirch 在 中提供:issue:`21800`。)
图像
what() 函数现在可以识别 OpenEXR 格式(由 Martin Vignali 和 Claudiu Popa 在 :issue:`20295` 中贡献),以及 WebP 格式(由 Fabrice Aneche 和 Cludiu Popa 在 :issue:`20197` 中贡献。)
导入库
util.LazyLoader 类允许在启动时间很重要的应用程序中延迟加载模块。 (由 Brett Cannon 在 :issue:`17621` 中贡献。)
abc.InspectLoader.source_to_code() 方法现在是一个静态方法。 这使得通过运行 exec(code, module.__dict__)
使用从字符串编译的代码更容易初始化模块对象。 (由 Brett Cannon 在 中提供:issue:`21156`。)
新的 util.module_from_spec() 函数现在是创建新模块的首选方式。 与直接创建 types.ModuleType 实例相反,这个新函数将根据传入的规范对象设置各种导入控制的属性。 (由 Brett Cannon 在 :issue:`20383` 中提供。)
检查
Signature 和 Parameter 类现在都可以选择和散列。 (由 Yury Selivanov 在 :issue:`20726` 和 :issue:`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 在 中提供:issue:`24190`。)
新的类方法 Signature.from_callable() 使 Signature 的子类化更容易。 (由 Yury Selivanov 和 Eric Snow 在 :issue:`17373` 中贡献。)
signature() 函数现在接受 follow_wrapped 可选关键字参数,当设置为 False
时,禁用 __wrapped__
链接的自动跟随。 (由 Yury Selivanov 在 :issue:`20691` 中贡献。)
添加了一组用于检查 协程函数 和 协程对象 的新函数:iscoroutine()、iscoroutinefunction()、 ]isawaitable()、getcoroutinelocals() 和 getcoroutinestate()。 (由 Yury Selivanov 在 :issue:`24017` 和 :issue:`24400` 中贡献。)
stack()、trace()、getouterframes() 和 getinnerframes() 函数现在返回命名元组列表。 (由 Daniel Shahaf 在 :issue:`16808` 中提供。)
io
一种新的 BufferedIOBase.readinto1() 方法,它最多使用一次对底层原始流的 RawIOBase.read() 或 RawIOBase.readinto() 方法的调用. (由 Nikolaus Rath 在 :issue:`20578` 中提供。)
IP地址
IPv4Network 和 IPv6Network 类现在都接受 (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 在 :issue:`16531` 中提供。)
IPv4Network 和 IPv6Network 类的新 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 在 :issue:`20480` 中贡献。)
json
json.tool 命令行界面现在保留传入输入的 JSON 对象中键的顺序。 新的 --sort-keys
选项可用于按字母顺序对键进行排序。 (由 Berker Peksag 在 中提供:issue:`21650`。)
JSON 解码器现在引发 JSONDecodeError 而不是 ValueError 以提供有关错误的更好的上下文信息。 (由 Serhiy Storchaka 在 :issue:`19361` 中提供。)
线缓存
新的 lazycache() 函数可用于捕获有关非基于文件的模块的信息,以允许稍后通过 getline() 获取其行。 这避免了在实际需要一行之前执行 I/O,而不必无限期地携带模块全局变量。 (由 Robert Collins 在 :issue:`17911` 中提供。)
语言环境
新的 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 在 中提供:issue:`13918`。)
日志记录
所有日志记录方法(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 在 :issue:`20537` 中贡献。)
handlers.HTTPHandler 类现在接受一个可选的 ssl.SSLContext 实例来配置 HTTP 连接中使用的 SSL 设置。 (由 Alex Gaynor 在 :issue:`22788` 中提供。)
handlers.QueueListener 类现在采用 respect_handler_level 关键字参数,如果设置为 True
,会将消息传递给处理程序,并将处理程序级别考虑在内。 (由 Vinay Sajip 提供。)
lzma
LZMADecompressor.decompress() 方法现在接受一个可选的 max_length 参数来限制解压缩数据的最大大小。 (由 Martin Panter 在 :issue:`15955` 中提供。)
数学
math 模块中添加了两个新常量:inf 和 nan。 (由 Mark Dickinson 在 :issue:`23185` 中贡献。)
新函数 isclose() 提供了一种测试近似相等性的方法。 (由 Chris Barker 和 Tal Einat 在 :issue:`24270` 中提供。)
添加了一个新的 gcd() 函数。 fractions.gcd() 函数现已弃用。 (由 Mark Dickinson 和 Serhiy Storchaka 在 中提供:issue:`22486`。)
操作员
attrgetter()、itemgetter() 和 methodcaller() 对象现在支持酸洗。 (由 Josh Rosenberg 和 Serhiy Storchaka 在 中提供:issue:`22955`。)
新的 matmul() 和 imatmul() 函数来执行矩阵乘法。 (由 Benjamin Peterson 在 中提供:issue:`21176`。)
操作系统
添加了返回 DirEntry 对象迭代器的新 scandir() 函数。 如果可能,scandir() 在扫描目录时提取文件属性,无需执行后续系统调用来确定文件类型或属性,这可能会显着提高性能。 (由 Ben Hoyt 在 Victor Stinner 的帮助下在 :issue:`22524` 中贡献。)
在 Windows 上,现在可以使用新的 stat_result.st_file_attributes 属性。 它对应于GetFileInformationByHandle()
返回的BY_HANDLE_FILE_INFORMATION
结构的dwFileAttributes
成员。 (由 Ben Hoyt 在 中提供:issue:`21719`。)
urandom() 函数现在在 Linux 3.17 或更高版本上使用 getrandom()
系统调用,在 OpenBSD 5.6 和更高版本上使用 getentropy()
,无需使用 /dev/urandom
] 并避免由于潜在的文件描述符耗尽而导致的失败。 (由 Victor Stinner 在 中提供:问题:`22181`。)
新的 get_blocking() 和 set_blocking() 函数允许获取和设置文件描述符的阻塞模式(O_NONBLOCK。)(由 Victor Stinner 在 中贡献:问题:`22054`。)
Windows 现在支持 truncate() 和 ftruncate() 函数。 (由 Steve Dower 在 中提供:issue:`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 在 中提供:issue:`10395`。)
路径库
新的 Path.samefile() 方法可用于检查路径是否与另一个路径指向同一个文件,该路径可以是另一个 Path 对象,也可以是字符串:
>>> import pathlib
>>> p1 = pathlib.Path('/etc/hosts')
>>> p2 = pathlib.Path('/etc/../etc/hosts')
>>> p1.samefile(p2)
True
(由 Vajrasky Kok 和 Antoine Pitrou 在 :issue:`19775` 中提供。)
Path.mkdir() 方法现在接受一个新的可选 exist_ok 参数来匹配 mkdir -p
和 os.makedirs() 功能。 (由 Berker Peksag 在 中提供:issue:`21539`。)
有一个新的 Path.expanduser() 方法来扩展 ~
和 ~user
前缀。 (由 Serhiy Storchaka 和 Cludiu Popa 在 :issue:`19776` 中提供。)
新的 Path.home() 类方法可用于获取表示用户主目录的 Path 实例。 (由 Victor Salgado 和 Mayank Tripathi 在 :issue:`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 在 :issue:`20218` 中提供。)
泡菜
嵌套对象,例如未绑定方法或嵌套类,现在可以使用早于协议版本 4 的 pickle 协议 进行酸洗。 协议版本 4 已经支持这些情况。 (由 Serhiy Storchaka 在 中提供:issue:`23611`。)
关于
后向断言中现在允许对具有固定长度的组进行引用和条件引用:
>>> 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 在 中提供:issue:`9179`。)
正则表达式中的捕获组数量不再限制为 100。 (由 Serhiy Storchaka 在 中提供:issue:`22437`。)
sub() 和 subn() 函数现在用空字符串替换不匹配的组,而不是引发异常。 (由 Serhiy Storchaka 在 中提供:issue:`1519638`。)
re.error 异常有新的属性,msg、pattern、pos、lineno和 ]colno,提供关于错误的更好的上下文信息:
>>> re.compile("""
... (?x)
... .++
... """)
Traceback (most recent call last):
...
sre_constants.error: multiple repeat at position 16 (line 3, column 7)
(由 Serhiy Storchaka 在 中提供:issue:`22578`。)
休蒂尔
move() 函数现在接受 copy_function 参数,例如允许使用 copy() 函数而不是默认的 copy2 () 如果移动时需要忽略文件元数据。 (由克劳迪乌·波帕在 中提供:issue:`19840`。)
make_archive() 函数现在支持 xztar 格式。 (由 Serhiy Storchaka 在 中提供:issue:`5411`。)
信号
在 Windows 上,set_wakeup_fd() 函数现在也支持套接字句柄。 (由 Victor Stinner 在 中提供:issue:`22018`。)
signal 模块中的各种 SIG*
常量已转换为 Enums。 这允许在调试期间打印有意义的名称,而不是整数“幻数”。 (由 Giampaolo Rodola 在 中提供:issue:`21076`。)
smtpd
SMTPServer 和 SMTPChannel 类现在都接受 decode_data 关键字参数来确定 SMTP 事务的 DATA
部分是否使用 [ X196X] 编解码器或作为字节字符串提供给 SMTPServer.process_message() 方法。 出于向后兼容性原因,默认值为 True
,但在 Python 3.6 中将更改为 False
。 如果 decode_data 设置为 False
,则 process_message
方法必须准备好接受关键字参数。 (由 Maciej Szulik 在 :issue:`19662` 中提供。)
如果 decode_data 已设置 [ X139X]。 如果客户端在 MAIL
命令上指定了 BODY=8BITMIME
,则会通过 mail_options 关键字将其传递给 SMTPServer.process_message()。 (由 Milan Oberkirch 和 R. 中的 David Murray:问题:`21795`。)
SMTPServer 类现在还支持 SMTPUTF8
扩展(RFC 6531:国际化电子邮件)。 如果客户端在 MAIL
命令上指定了 SMTPUTF8 BODY=8BITMIME
,它们将通过 mail_options 关键字传递给 SMTPServer.process_message()。 process_message
方法负责正确处理 SMTPUTF8
数据。 (由 Milan Oberkirch 在 中提供:issue:`21725`。)
现在可以在 SMTPServer 构造函数中直接或通过名称解析提供 IPv6 地址,并使其成功连接。 (由 Milan Oberkirch 在 中提供:issue:`14758`。)
smtplib
新的 SMTP.auth() 方法提供了一种实现自定义身份验证机制的便捷方法。 (由 Milan Oberkirch 在 中提供:issue:`15014`。)
SMTP.set_debuglevel() 方法现在接受一个额外的调试级别 (2),它在调试消息中启用时间戳。 (由 Gavin Chappell 和 Maciej Szulik 在 :issue:`16914` 中提供。)
SMTP.sendmail() 和 SMTP.send_message() 方法现在都支持 RFC 6531 (SMTPUTF8)。 (由 Milan Oberkirch 和 R. 中的 David Murray:问题:`22027`。)
插座
具有超时功能的函数现在使用单调时钟,而不是系统时钟。 (由 Victor Stinner 在 中提供:问题:`22043`。)
新的 socket.sendfile() 方法允许使用 UNIX 上的高性能 os.sendfile() 函数通过套接字发送文件,导致上传从 2 到 3比使用普通 socket.send() 时快几倍。 (由 Giampaolo Rodola 在 中提供:issue:`17552`。)
socket.sendall() 方法不再在每次接收或发送字节时重置套接字超时。 套接字超时现在是发送所有数据的最大总持续时间。 (由 Victor Stinner 在 中提供:问题:`23853`。)
socket.listen() 方法的 backlog 参数现在是可选的。 默认情况下,它设置为 SOMAXCONN 或 128
,以较小者为准。 (由 Charles-François Natali 在 :issue:`21455` 中提供。)
ssl
内存生物支持
(由 Geert Jansen 在 中提供:issue:`21965`。)
添加了新的 SSLObject 类以在 SSLSocket 的网络 I/O 功能不需要或不是最理想的情况下提供 SSL 协议支持。 SSLObject
代表一个 SSL 协议实例,但没有实现任何网络 I/O 方法,而是提供了一个内存缓冲区接口。 新的 MemoryBIO 类可用于在 Python 和 SSL 协议实例之间传递数据。
内存 BIO SSL 支持主要用于实现异步 I/O 的框架,其中 SSLSocket 的就绪模型(“选择/轮询”)效率低下。
新的 SSLContext.wrap_bio() 方法可用于创建新的 SSLObject
实例。
应用层协议协商支持
(由 Benjamin Peterson 在 :issue:`20188` 中提供。)
在存在 OpenSSL 支持的情况下,ssl 模块现在实现了 应用层协议协商 TLS 扩展,如 RFC 7301 中所述。
新的 SSLContext.set_alpn_protocols() 可用于指定套接字应在 TLS 握手期间通告哪些协议。
新的 SSLSocket.selected_alpn_protocol() 返回在 TLS 握手期间选择的协议。 HAS_ALPN 标志指示是否存在 ALPN 支持。
其他变化
有一个新的 SSLSocket.version() 方法来查询正在使用的实际协议版本。 (由 Antoine Pitrou 在 :issue:`20421` 中提供。)
SSLSocket 类现在实现了 SSLSocket.sendfile()
方法。 (由 Giampaolo Rodola 在 中提供:issue:`17552`。)
如果操作会阻塞,SSLSocket.send()
方法现在会在非阻塞套接字上引发 ssl.SSLWantReadError 或 ssl.SSLWantWriteError 异常。 以前,它会返回 0
。 (由 Nikolaus Rath 在 :issue:`20951` 中提供。)
cert_time_to_seconds() 函数现在将输入时间解释为 UTC 而不是本地时间,根据 RFC 5280。 此外,返回值始终是 int。 (由 Akira Li 在 :issue:`19940` 中贡献。)
新的 SSLObject.shared_ciphers()
和 SSLSocket.shared_ciphers() 方法返回客户端在握手期间发送的密码列表。 (由 Benjamin Peterson 在 中提供:issue:`23186`。)
的 SSLSocket.do_handshake()、SSLSocket.read()、SSLSocket.shutdown()
和 SSLSocket.write() 方法SSLSocket 类不再在每次接收或发送字节时重置套接字超时。 套接字超时现在是该方法的最大总持续时间。 (由 Victor Stinner 在 中提供:问题:`23853`。)
match_hostname() 函数现在支持 IP 地址匹配。 (由 Antoine Pitrou 在 中提供:issue:`23239`。)
sqlite3
Row 类现在完全支持序列协议,特别是 reversed() 迭代和切片索引。 (由 Claudiu Popa 在 中提供:issue:`10203`;由 Lucas Sinclair、Jessica McKellar 和 Serhiy Storchaka 在 中提供:issue:`13583`。)
子流程
添加了新的 run() 函数。 它运行指定的命令并返回一个 CompletedProcess 对象,它描述了一个完成的进程。 新的 API 更加一致,是在 Python 代码中调用子流程的推荐方法,这些子流程不需要保持与早期 Python 版本的兼容性。 (由 Thomas Kluyver 在 :issue:`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')
系统
新的 set_coroutine_wrapper()
函数允许设置一个全局钩子,每当 协程对象 由 async def 函数创建时,该钩子都会被调用。 相应的 get_coroutine_wrapper()
可用于获取当前设置的包装器。 这两个函数都是 临时 ,仅用于调试目的。 (由 Yury Selivanov 在 :issue:`24017` 中贡献。)
新的 is_finalizing() 函数可用于检查 Python 解释器是否正在 关闭 。 (由 Antoine Pitrou 在 中提供:issue:`22696`。)
tar文件
open() 函数的 mode 参数现在接受 "x"
请求独占创建。 (由 Berker Peksag 在 中提供:issue:`21717`。)
TarFile.extractall() 和 TarFile.extract() 方法现在采用关键字参数 numeric_owner。 如果设置为 True
,提取的文件和目录将由 tarfile 中的数字 uid
和 gid
拥有。 如果设置为 False
(默认值,以及 3.5 之前版本中的行为),它们将由 tarfile 中的命名用户和组拥有。 (由 Michael Vogt 和 Eric Smith 在 :issue:`23193` 中提供。)
TarFile.list() 现在接受一个可选的 members 关键字参数,该参数可以设置为 TarFile.getmembers() 返回的列表的子集。 (由 Serhiy Storchaka 在 中提供:issue:`21549`。)
时间
新的命令行选项 -u
或 --unit=U
可用于指定定时器输出的时间单位。 支持的选项有 usec
、msec
或 sec
。 (由 Julian Gindi 在 :issue:`18983` 中贡献。)
timeit() 函数有一个新的 globals 参数,用于指定代码将在其中运行的命名空间。 (由 Ben Roberts 在 :issue:`2527` 中贡献。)
特金特
用于在 Windows 上设置 Tcl/Tk 环境的 tkinter._fix
模块已被替换为 _tkinter
模块中的私有函数,该函数不会永久更改环境变量。 (由 Zachary Ware 在 :issue:`20035` 中提供。)
追溯
新的 walk_stack() 和 walk_tb() 函数可以方便地遍历框架和回溯对象。 (由 Robert Collins 在 :issue:`17911` 中提供。)
新的轻量级类:TracebackException、StackSummary 和 FrameSummary。 (由 Robert Collins 在 :issue:`17911` 中提供。)
print_tb() 和 print_stack() 函数现在都支持 limit 参数的负值。 (由 Dmitry Kazakov 在 中提供:issue:`22619`。)
类型
一个新的 coroutine() 函数将 generator 和 generator-like 对象转换为 awaitables。 (由 Yury Selivanov 在 :issue:`24017` 中贡献。)
一种名为 CoroutineType 的新类型,用于由 async def 函数创建的 coroutine 对象。 (由 Yury Selivanov 在 :issue:`24400` 中贡献。)
单元测试
TestLoader.loadTestsFromModule() 方法现在接受仅关键字参数 pattern,该参数作为第三个参数传递给 load_tests
。 找到的包现在检查 load_tests
,不管它们的路径是否匹配 pattern,因为包名不可能匹配默认模式。 (由罗伯特柯林斯和巴里 A. 中的华沙:问题:`16662`。)
Unittest 发现错误现在在 TestLoader 实例的 TestLoader.errors 属性中公开。 (由 Robert Collins 在 :issue:`19746` 中提供。)
一个新的命令行选项 --locals
在回溯中显示局部变量。 (由 Robert Collins 在 中提供:issue:`22936`。)
单元测试.mock
Mock 类有以下改进:
- 类构造函数有一个新的 unsafe 参数,这会导致模拟对象在以
"assert"
开头的属性名称上引发 AttributeError。 (由 Kushal Das 在 中提供:issue:`21238`。) - 一个新的 Mock.assert_not_Called() 方法来检查模拟对象是否被调用。 (由 Kushal Das 在 中提供:issue:`21262`。)
MagicMock 类现在支持 __truediv__()
、__divmod__()
和 __matmul__()
运算符。 (由 Johannes Baiter 在 :issue:`20968` 和 Håkan Lövdahl 在 :issue:`23581` 和 :issue:`23568` 中贡献。)
在修补内置名称时,不再需要将 create=True
显式传递给 patch() 函数。 (由 Kushal Das 在 中提供:issue:`17660`。)
网址库
新的 request.HTTPPasswordMgrWithPriorAuth 类允许管理 HTTP 基本身份验证凭据,以消除不必要的 401
响应处理,或在第一个请求时无条件发送凭据以便与服务器进行通信如果未发送 Authorization
标头,则返回 404
响应而不是 401
。 (由 Matej Cepl 在 :issue:`19494` 和 Akshit Khurana 在 :issue:`7159` 中贡献。)
parse.urlencode() 函数的新 quote_via 参数提供了一种在需要时控制查询部分编码的方法。 (由 Samwyse 和 Arnon Yaari 在 :issue:`13866` 中提供。)
request.urlopen() 函数接受一个 ssl.SSLContext 对象作为 context 参数,它将用于 HTTPS 连接。 (由 Alex Gaynor 在 :issue:`22366` 中提供。)
parse.urljoin() 已更新为使用 RFC 3986 语义来解析相对 URL,而不是 RFC 1808 和 RFC 2396。 (由 Demian Brecht 和 Senthil Kumaran 在 中提供:issue:`22118`。)
wsgiref
headers.Headers 类构造函数的 headers 参数现在是可选的。 (由 Pablo Torres Navarrete 和 SilentGhost 在 中提供:issue:`5800`。)
xmlrpc
client.ServerProxy 类现在支持 上下文管理器 协议。 (由克劳迪乌·波帕在 中提供:issue:`20627`。)
client.ServerProxy 构造函数现在接受一个可选的 ssl.SSLContext 实例。 (由 Alex Gaynor 在 :issue:`22960` 中提供。)
sax文件
SAX 解析器现在支持 xmlreader.InputSource 对象的字符流。 (由 Serhiy Storchaka 在 中提供:issue:`2175`。)
parseString() 现在接受一个 str 实例。 (由 Serhiy Storchaka 在 中提供:issue:`10590`。)
压缩文件
ZIP 输出现在可以写入不可搜索的流。 (由 Serhiy Storchaka 在 中提供:issue:`23252`。)
ZipFile.open() 方法的 mode 参数现在接受 "x"
请求独占创建。 (由 Serhiy Storchaka 在 中提供:issue:`21717`。)
其他模块级更改
mmap、ossaudiodev、socket、ssl和codecs模块中的许多函数现在接受可写 ]字节类对象。 (由 Serhiy Storchaka 在 中提供:issue:`23001`。)
优化
os.walk() 函数在 POSIX 系统上速度提高了 3 到 5 倍,在 Windows 上速度提高了 7 到 20 倍。 这是使用新的 os.scandir() 函数完成的,该函数公开来自底层 readdir
或 FindFirstFile
/FindNextFile
系统调用的文件信息。 (由 Ben Hoyt 在 Victor Stinner 的帮助下在 :issue:`23605` 中提供。)
bytes(int)
(由零字节填充)的构造速度更快,并且为大对象使用更少的内存。 使用 calloc()
代替 malloc()
为这些对象分配内存。 (由 Victor Stinner 在 中提供:问题:`21233`。)
ipaddress IPv4Network 和 IPv6Network 上的一些操作已经大幅加速,例如 subnets(), supernet()[ X155X]、summarize_address_range()、collapse_addresses()。 加速范围可以从 3 到 15 倍。 (由 Antoine Pitrou、Michel Albert 和 Markus 在 :issue:`21486`, :issue:`21487`, :issue:`20826` 中贡献, :issue:`23266`。)
ipaddress 对象的酸洗经过优化以产生明显更小的输出。 (由 Serhiy Storchaka 在 中提供:issue:`23133`。)
io.BytesIO 上的许多操作现在都快了 50% 到 100%。 (由 Serhiy Storchaka 在 :issue:`15381` 和 David Wilson 在 :issue:`22003` 中贡献。)
marshal.dumps() 函数现在更快:对于典型数据,版本 3 和 4 为 65–85%,版本 0 到 2 为 20–25%,在最佳情况下可达 5 倍。 (由 Serhiy Storchaka 在 :issue:`20416` 和 :issue:`23344` 中贡献。)
UTF-32 编码器现在快了 3 到 7 倍。 (由 Serhiy Storchaka 在 :issue:`15027` 中提供。)
正则表达式现在最多可以解析为 10% faster。 (由 Serhiy Storchaka 在 :issue:`19380` 中提供。)
json.dumps() 函数经过优化,可以在 ensure_ascii=False
和 ensure_ascii=True
上运行一样快。 (由 Naoki Inada 在 :issue:`23206` 中提供。)
PyObject_IsInstance() 和 PyObject_IsSubclass() 函数在第二个参数具有 type 作为其元类的常见情况下已被加速。 (由 中的 Georg Brandl 贡献:issue:`22540`。)
方法缓存略有改进,在某些基准测试中性能提升高达 5%。 (由 Antoine Pitrou 在 中提供:issue:`22847`。)
random 模块中的对象现在在 64 位版本上使用 50% less 内存。 (由 Serhiy Storchaka 在 中提供:issue:`23488`。)
property() getter 调用最多可达 25% faster。 (由 Joe Jevnik 在 :issue:`23910` 中提供。)
fractions.Fraction 的实例化现在高达 30% faster。 (由 Stefan Behnel 在 中提供:issue:`22464`。)
字符串方法 find()、rfind()、split()、partition() 和 in字符串运算符现在搜索 1 个字符的子字符串的速度要快得多。 (由 Serhiy Storchaka 在 中提供:issue:`23573`。)
构建和 C API 更改
添加了新的 calloc
功能:
(由 Victor Stinner 在 中提供:问题:`21233`。)
新的编码/解码辅助函数:
- Py_DecodeLocale()(替换为
_Py_char2wchar()
), - Py_EncodeLocale()(替换
_Py_wchar2char()
)。
(由 Victor Stinner 在 中提供:问题:`18395`。)
一个新的 PyCodec_NameReplaceErrors() 函数用 \N{...}
转义替换 unicode 编码错误。 (由 Serhiy Storchaka 在 :issue:`19676` 中提供。)
新的 PyErr_FormatV() 函数类似于 PyErr_Format(),但接受 va_list
参数。 (由 Antoine Pitrou 在 :issue:`18711` 中提供。)
一个新的 PyExc_RecursionError
例外。 (由 Georg Brandl 在 中提供:issue:`19235`。)
新的 PyModule_FromDefAndSpec()、PyModule_FromDefAndSpec2() 和 PyModule_ExecDef() 函数由 [X143X][X143X] 引入-phase 扩展模块初始化。 (由 Petr Viktorin 在 中提供:issue:`24268`。)
新的 PyNumber_MatrixMultiply() 和 PyNumber_InPlaceMatrixMultiply() 函数来执行矩阵乘法。 (由 Benjamin Peterson 在 中贡献:issue:`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>
是构建扩展模块运行的硬件架构。 最常见的是i386
用于 32 位 Intel 平台或x86_64
用于 64 位 Intel(和 AMD)平台。<os>
总是linux-gnu
,除了为在 64 位平台上与 32 位 ABI 通信而构建的扩展,在这种情况下它是linux-gnu32
(和 [ X145X] 将是x86_64
)。
- 在 Windows 上,扩展模块文件名以
<debug>.cp<major><minor>-<platform>.pyd
结尾:<major>
是 Python 版本的主编号; 对于 Python 3.5,这是3
。<minor>
是 Python 版本的次要编号; 对于 Python 3.5,这是5
。<platform>
是构建扩展模块的平台,win32
用于 Win32、win_amd64
用于 Win64、win_ia64
用于 Windows Itanium 64 和win_arm
适用于 ARM 上的 Windows。- 如果在调试模式下内置,
<debug>
将为_d
,否则为空白。
- 在 OS X 平台上,扩展模块文件名现在以
-darwin.so
结尾。 - 在所有其他平台上,扩展模块文件名与 Python 3.4 相同。
已弃用
弃用的 Python 行为
在生成器中引发 StopIteration 异常现在将生成一个静默的 PendingDeprecationWarning,这将成为 Python 3.6 中的一个非静默的弃用警告,并将触发 RuntimeError蟒蛇 3.7。 有关详细信息,请参阅 PEP 479:更改生成器内部的 StopIteration 处理 。
弃用的 Python 模块、函数和方法
formatter 模块现已完全弃用,并且仍计划在 Python 3.6 中删除。
asyncio.async()
函数被弃用,取而代之的是 ensure_future()。
smtpd 模块过去总是使用 utf-8
编解码器解码电子邮件的数据部分。 这现在可以通过 SMTPServer 的新 decode_data 关键字来控制。 默认值为 True
,但不推荐使用此默认值。 使用适当的值指定 decode_data 关键字以避免弃用警告。
不推荐直接为 http.cookies.Morsel 对象的 key、value 和 coded_value 赋值。 请改用 set() 方法。 此外,不推荐使用 set() 的未记录的 LegalChars 参数,现在被忽略。
不推荐将格式字符串作为关键字参数 format_string 传递给 string.Formatter 类的 format() 方法。 (由 Serhiy Storchaka 在 中提供:issue:`23671`。)
platform.dist()
和 platform.linux_distribution()
函数现已弃用。 Linux 发行版使用太多不同的方式来描述自己,所以功能留给了一个包。 (由 Vajrasky Kok 和 Berker Peksag 在 中提供:issue:`1322`。)
以前未记录的 from_function
和 from_builtin
方法 inspect.Signature 已弃用。 改用新的 Signature.from_callable() 方法。 (由 Yury Selivanov 在 :issue:`24248` 中贡献。)
inspect.getargspec() 函数已弃用并计划在 Python 3.6 中删除。 (有关详细信息,请参阅 :issue:`20438`。)
inspect getfullargspec()、getcallargs() 和 formatargspec() 函数已被弃用,以支持 检查。签名() API。 (由 Yury Selivanov 在 :issue:`20438` 中贡献。)
getargvalues() 和 formatargvalues() 函数在 Python 3.5.0 发布时无意中被标记为已弃用。
现在不推荐使用 re.LOCALE 标志和 str 模式或 re.ASCII。 (由 Serhiy Storchaka 在 中提供:issue:`22407`。)
在正则表达式模式和替换模式中使用由 '\'
和 ASCII 字母组成的无法识别的特殊序列现在会引发弃用警告,并且将在 Python 3.6 中被禁止。 (由 Serhiy Storchaka 在 中提供:issue:`23622`。)
unittest.TestLoader.loadTestsFromModule() 方法的未记录和非官方 use_load_tests 默认参数现在已弃用并被忽略。 (由罗伯特柯林斯和巴里 A. 中的华沙:问题:`16662`。)
已移除
API 和功能删除
以下过时和以前弃用的 API 和功能已被删除:
__version__
属性已从电子邮件包中删除。 电子邮件代码已经很长时间没有与 stdlib 分开发布了,并且__version__
字符串在最近几个版本中没有更新。- ftplib 模块中的内部
Netrc
类在 3.4 中被弃用,现在已被删除。 (由 Matt Chaput 在 :issue:`6623` 中提供。) .pyo
文件的概念已被删除。- 临时 asyncio 模块中的 JoinableQueue 类在 3.4.4 中已被弃用,现在已被删除。 (由 A. 中的 Jesse Jiryu Davis:问题:`23464`。)
移植到 Python 3.5
本节列出了可能需要更改您的代码的先前描述的更改和其他错误修正。
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 中删除。 有关完整详细信息,请参阅 :issue:`13936`。
- 如果操作会阻塞,
ssl.SSLSocket.send()
方法现在会在非阻塞套接字上引发 ssl.SSLWantReadError 或 ssl.SSLWantWriteError。 以前,它会返回0
。 (由 Nikolaus Rath 在 :issue:`20951` 中提供。) - 生成器的
__name__
属性现在从函数名称设置,而不是从代码名称设置。 使用gen.gi_code.co_name
检索代号。 生成器还有一个新的__qualname__
属性,即限定名称,现在用于表示生成器 (repr(gen)
)。 (由 Victor Stinner 在 中提供:问题:`21205`。) - HTMLParser、
HTMLParser.error()
和HTMLParserError
异常的弃用“严格”模式和参数已被删除。 (由 Ezio Melotti 在 中贡献:issue:`15114`。)HTMLParser 的 convert_charrefs 参数现在默认为True
。 (由 Berker Peksag 在 中提供:issue:`21047`。) - 尽管它不是 API 的正式组成部分,但出于移植目的(即:修复测试)值得注意的是,以前形式为“'sometype' 不支持缓冲区协议”的错误消息现在的形式为“a bytes-like object 是必需的,而不是'sometype'”。 (由 Ezio Melotti 在 :issue:`16518` 中贡献。)
- 如果当前目录设置为不再存在的目录,则 FileNotFoundError 将不再引发,取而代之的是 find_spec() 将返回
None
而没有[ X192X] 在 sys.path_importer_cache 中缓存None
,这与典型情况不同(:issue:`22834`)。 - HTTP 状态代码和来自 http.client 和 http.server 的消息被重构为一个通用的 HTTPStatus 枚举。 http.client 和 http.server 中的值仍可用于向后兼容。 (由 Demian Brecht 在 中提供:issue:`21793`。)
- 当导入加载器定义
importlib.machinery.Loader.exec_module()
时,现在预计它也会定义create_module()
(现在引发 DeprecationWarning,这将是 Python 3.6 中的错误)。 如果加载器继承自 importlib.abc.Loader 那么就没有什么可做的,否则只需定义create_module()
以返回None
。 (由 Brett Cannon 在 中提供:issue:`23014`。) - re.split() 函数总是忽略空模式匹配,因此
"x*"
模式的工作方式与"x+"
相同,而"\b"
模式从未起作用. 现在 re.split() 会在模式匹配空字符串时发出警告。 为了兼容性,使用从不匹配空字符串的模式(例如"x+"
而不是"x*"
)。 只能匹配空字符串的模式(例如"\b"
)现在会引发错误。 (由 Serhiy Storchaka 在 中提供:issue:`22818`。) - http.cookies.Morsel 类似 dict 的接口已经变得自洽:morsel 比较现在考虑 key 和 value,copy( ) 现在产生 Morsel 实例而不是 dict,并且 update() 现在将在更新中的任何键时引发异常字典无效。 此外,不推荐使用 set() 的未记录的 LegalChars 参数,现在已被忽略。 (由 Demian Brecht 在 中提供:issue:`2211`。)
- PEP 488 从 Python 中删除了
.pyo
文件,并在.pyc
文件名中引入了可选的opt-
标签。 importlib.util.cache_from_source() 获得了一个 优化 参数来帮助控制opt-
标签。 因此,现在不推荐使用该函数的 debug_override 参数。 .pyo 文件也不再支持作为 Python 解释器的文件参数,因此在单独分发时没有任何作用(即 无源代码分发)。 由于 Python 3.5 中字节码的幻数发生了变化,因此无论此 PEP 如何,Python 以前版本中的所有旧 .pyo 文件都无效。 - socket 模块现在在 linux 3.6 及更高版本上导出 CAN_RAW_FD_FRAMES 常量。
- ssl.cert_time_to_seconds() 函数现在将输入时间解释为 UTC 而不是本地时间,根据 RFC 5280。 此外,返回值始终是 int。 (由 Akira Li 在 :issue:`19940` 中贡献。)
pygettext.py
工具现在对 POT-Creation-Date 标头中的时区使用标准 +NNNN 格式。- smtplib 模块现在使用 sys.stderr 而不是之前的模块级
stderr
变量进行调试输出。 如果您的(测试)程序依赖于修补模块级变量来捕获调试输出,则您需要更新它以捕获 sys.stderr。 - str.startswith() 和 str.endswith() 方法在找到空字符串并且索引完全超出范围时不再返回
True
。 (由 Serhiy Storchaka 在 中提供:issue:`24284`。) - inspect.getdoc() 函数现在返回从基类继承的文档字符串。 如果继承的文档合适,则不再需要复制文档字符串。 要取消继承的字符串,必须指定一个空字符串(或者可能会填写文档)。 此更改会影响 pydoc 模块和 help() 函数的输出。 (由 Serhiy Storchaka 在 中提供:issue:`15582`。)
- 嵌套的 functools.partial() 调用现在扁平化了。 如果您依赖之前的行为,您现在可以向 functools.partial() 对象添加属性,也可以创建 functools.partial() 的子类。 (由 Alexander Belopolsky 在 :issue:`7830` 中提供。)
C API 的变化
- (非公开)
PyMemoryViewObject
结构的未记录的format
成员已被删除。 所有依赖memoryobject.h
中相关部分的扩展都必须重建。 PyMemAllocator
结构重命名为 PyMemAllocatorEx 并添加了新的calloc
字段。- 删除了泄露引用的未记录的宏
PyObject_REPR
。 在类似 PyUnicode_FromFormat() 的函数中使用格式字符%R
来格式化对象的 repr()。 (由 Serhiy Storchaka 在 中提供:issue:`22453`。) - 由于缺少
__module__
属性会破坏酸洗和自省,现在为没有__module__
属性的内置类型引发弃用警告。 这将是未来的 AttributeError 。 (由 Serhiy Storchaka 在 :issue:`20204` 中提供。) - 作为 PEP 492 实现的一部分,PyTypeObject 的
tp_reserved
插槽被替换为tp_as_async
插槽。 有关新类型、结构和功能,请参阅 协程对象 。
Python 3.5.4 中的显着变化
新的 make regen-all 构建目标
为了简化交叉编译,并确保在不需要现有 Python 版本可用的情况下可靠地编译 CPython,基于自动工具的构建系统不再尝试根据文件修改时间隐式地重新编译生成的文件。
相反,添加了一个新的 make regen-all
命令以在需要时强制重新生成这些文件(例如 在已经基于预先生成的版本构建了 Python 的初始版本之后)。
还定义了更多选择性的再生目标 - 有关详细信息,请参阅 :source:`Makefile.pre.in`。
(由 Victor Stinner 在 中提供:问题:`23404`。)
3.5.4 版中的新功能。
移除 make touch 构建目标
make touch
构建目标以前用于通过更新修改时间请求隐式重新生成生成的文件已被删除。
它已被新的 make regen-all
目标取代。
(由 Victor Stinner 在 中提供:问题:`23404`。)
在 3.5.4 版中更改。