Python 3.6 的新特性 — Python 文档
Python 3.6 中的新功能
- 编辑
- 埃尔维斯·普兰斯克维奇 < 猫王@magic.io >, 尤里·塞利瓦诺夫 < yury@magic.io >
本文解释了 Python 3.6 中与 3.5 相比的新特性。 Python 3.6 于 2016 年 12 月 23 日发布。 请参阅 changelog 以获取完整的更改列表。
摘要 – 发布亮点
新的语法特性:
新的库模块:
CPython 实现改进:
- dict 类型已被重新实现以使用 更紧凑的表示 ,基于 由 Raymond Hettinger 提出的建议,类似于 PyPy dict 实现 . 与 Python 3.5 相比,这导致字典使用的内存减少了 20% 到 25%。
- 新协议简化了类创建的自定义。
- 类属性定义顺序为 现在保留 。
**kwargs
中元素的顺序现在 对应于关键字参数传递给函数的顺序 。- 添加了 DTrace 和 SystemTap 探测支持 。
- 新的 PYTHONMALLOC 环境变量现在可用于调试解释器内存分配和访问错误。
标准库的重大改进:
- asyncio 模块获得了新功能、显着的可用性和性能改进,以及大量错误修复。 从 Python 3.6 开始,
asyncio
模块不再是临时的,它的 API 被认为是稳定的。 - 一个新的 文件系统路径协议 已被实现以支持 类路径对象 。 在路径上运行的所有标准库函数都已更新以使用新协议。
- datetime 模块已获得对 Local Time Disambiguation 的支持。
- 打字模块获得了许多改进。
- tracemalloc 模块已经过重大改造,现在用于为 ResourceWarning 提供更好的输出,并为内存分配错误提供更好的诊断。 有关更多信息,请参阅 PYTHONMALLOC 部分 。
安全改进:
- 添加了新的 secrets 模块,以简化加密强伪随机数的生成,适用于管理帐户身份验证、令牌等机密信息。
- 在 Linux 上,os.urandom() 现在会阻塞,直到系统 urandom 熵池初始化以提高安全性。 有关基本原理,请参阅 PEP 524。
- hashlib 和 ssl 模块现在支持 OpenSSL 1.1.0。
- ssl 模块的默认设置和功能集已得到改进。
- hashlib 模块获得了对 BLAKE2、SHA-3 和 SHAKE 哈希算法以及 scrypt() 密钥推导函数的支持。
Windows 改进:
- PEP 528 和 PEP 529,Windows 文件系统和控制台编码更改为 UTF-8。
- 当用户没有指定版本(通过命令行参数或配置文件)时,
py.exe
启动器在交互使用时不再更喜欢 Python 2 而不是 Python 3。 shebang 行的处理保持不变 - 在这种情况下,“python”指的是 Python 2。 python.exe
和pythonw.exe
已被标记为长路径感知,这意味着 260 个字符的路径限制可能不再适用。 有关详细信息,请参阅 删除 MAX_PATH 限制 。- 可以添加
._pth
文件以强制隔离模式并完全指定所有搜索路径以避免注册表和环境查找。 有关更多信息,请参阅 文档 。 python36.zip
文件现在可以作为推断 PYTHONHOME 的地标。 有关更多信息,请参阅 文档 。
新特性
PEP 498:格式化字符串文字
PEP 498 引入了一种新的字符串文字:f-strings 或 格式化字符串文字。
格式化字符串文字以 'f'
为前缀,类似于 str.format() 接受的格式字符串。 它们包含用花括号包围的替换字段。 替换字段是表达式,在运行时计算,然后使用 format() 协议格式化:
>>> name = "Fred"
>>> f"He said his name is {name}."
'He said his name is Fred.'
>>> width = 10
>>> precision = 4
>>> value = decimal.Decimal("12.34567")
>>> f"result: {value:{width}.{precision}}" # nested fields
'result: 12.35'
PEP 526:变量注释的语法
PEP 484 引入了函数参数类型注释的标准,又名 键入提示。 此 PEP 向 Python 添加了用于注释变量类型(包括类变量和实例变量)的语法:
primes: List[int] = []
captain: str # Note: no initial value!
class Starship:
stats: Dict[str, int] = {}
就像函数注解一样,Python 解释器没有给变量注解附加任何特定的含义,只将它们存储在类或模块的 __annotations__
属性中。
与静态类型语言中的变量声明相比,注释语法的目标是通过抽象语法树和 __annotations__
属性提供一种简单的方法来为第三方工具和库指定结构化类型元数据。
PEP 515:数字文字中的下划线
PEP 515 添加了在数字文字中使用下划线的功能,以提高可读性。 例如:
>>> 1_000_000_000_000_000
1000000000000000
>>> 0x_FF_FF_FF_FF
4294967295
数字之间和任何基数说明符之后都允许使用单个下划线。 不允许在一行中使用前导、尾随或多个下划线。
字符串格式 语言现在也支持 '_'
选项,以表示使用下划线作为浮点表示类型和整数表示类型的千位分隔符 'd'
. 对于整数表示类型 'b'
、'o'
、'x'
和 'X'
,将每 4 位插入下划线:
>>> '{:_}'.format(1000000)
'1_000_000'
>>> '{:_x}'.format(0xFFFFFFFF)
'ffff_ffff'
PEP 525:异步生成器
PEP 492 在 Python 3.5 中引入了对原生协程和 async
/ await
语法的支持。 Python 3.5 实现的一个显着限制是无法在同一函数体中使用 await
和 yield
。 在 Python 3.6 中,此限制已取消,可以定义 异步生成器 :
async def ticker(delay, to):
"""Yield numbers from 0 to *to* every *delay* seconds."""
for i in range(to):
yield i
await asyncio.sleep(delay)
新语法允许更快、更简洁的代码。
PEP 530:异步理解
PEP 530 添加了对在列表、集合、字典推导式和生成器表达式中使用 async for
的支持:
result = [i async for i in aiter() if i % 2]
此外,await
表达式支持所有类型的推导式:
result = [await fun() for fun in funcs if await condition()]
PEP 487:更简单的自定义类创建
现在可以在不使用元类的情况下自定义子类的创建。 每当创建新的子类时,都会在基类上调用新的 __init_subclass__
类方法:
class PluginBase:
subclasses = []
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
cls.subclasses.append(cls)
class Plugin1(PluginBase):
pass
class Plugin2(PluginBase):
pass
为了允许零参数 super() 调用从 __init_subclass__() 实现正常工作,自定义元类必须确保新的 __classcell__
命名空间条目传播到type.__new__
(如 创建类对象 中所述)。
PEP 487:描述符协议增强
PEP 487 扩展了描述符协议以包含新的可选 __set_name__() 方法。 每当定义一个新类时,将在定义中包含的所有描述符上调用新方法,为它们提供对正在定义的类的引用以及在类命名空间中为描述符提供的名称。 换句话说,描述符的实例现在可以知道所有者类中描述符的属性名称:
class IntField:
def __get__(self, instance, owner):
return instance.__dict__[self.name]
def __set__(self, instance, value):
if not isinstance(value, int):
raise ValueError(f'expecting integer in {self.name}')
instance.__dict__[self.name] = value
# this is the new initializer:
def __set_name__(self, owner, name):
self.name = name
class Model:
int_field = IntField()
PEP 519:添加文件系统路径协议
文件系统路径历来表示为 str 或 bytes 对象。 这导致编写对文件系统路径进行操作的代码的人假设此类对象只是这两种类型中的一种(表示文件描述符的 int 不算作不是文件路径) . 不幸的是,这种假设阻止了文件系统路径的替代对象表示,如 pathlib 使用预先存在的代码,包括 Python 的标准库。
为了解决这种情况,定义了一个由 os.PathLike 表示的新接口。 通过实现 __fspath__()
方法,一个对象表示它表示一条路径。 然后,对象可以将文件系统路径的低级表示提供为 str 或 bytes 对象。 这意味着一个对象被认为是 path-like 如果它实现了 os.PathLike 或者是一个 str 或 bytes 对象代表一个文件系统路径。 代码可以使用 os.fspath()、os.fsdecode() 或 os.fsencode() 显式获取 str和/或 bytes 路径类对象的表示。
内置的 open() 函数已更新为接受 os.PathLike 对象,与 os 和 os 中的所有相关函数一样。 path 模块,以及标准库中的大多数其他函数和类。 os.DirEntry 类和 pathlib 中的相关类也已更新以实现 os.PathLike。
希望更新文件系统路径上操作的基本功能将导致第三方代码隐式支持所有 类路径对象 无需任何代码更改,或者至少是非常少的代码更改(例如 在对类似路径的对象进行操作之前,在代码的开头调用 os.fspath())。
以下是一些示例,说明新接口如何允许 pathlib.Path 与预先存在的代码一起更轻松、更透明地使用:
>>> import pathlib
>>> with open(pathlib.Path("README")) as f:
... contents = f.read()
...
>>> import os.path
>>> os.path.splitext(pathlib.Path("some_file.txt"))
('some_file', '.txt')
>>> os.path.join("/a/b", pathlib.Path("c"))
'/a/b/c'
>>> import os
>>> os.fspath(pathlib.Path("some_file.txt"))
'some_file.txt'
(由 Brett Cannon、Ethan Furman、Dusty Phillips 和 Jelle Zijlstra 实施。)
PEP 495:当地时间消歧
在世界上大多数地方,本地时钟已经并且将会有时间向后移动。 在那些时间里,引入了时间间隔,其中本地时钟在同一天两次显示相同的时间。 在这些情况下,显示在本地时钟上(或存储在 Python 日期时间实例中)的信息不足以及时识别特定时刻。
PEP 495 将新的 fold 属性添加到 datetime.datetime 和 datetime.time 类的实例以区分在当地时间相同的两个时刻之间:
>>> u0 = datetime(2016, 11, 6, 4, tzinfo=timezone.utc)
>>> for i in range(4):
... u = u0 + i*HOUR
... t = u.astimezone(Eastern)
... print(u.time(), 'UTC =', t.time(), t.tzname(), t.fold)
...
04:00:00 UTC = 00:00:00 EDT 0
05:00:00 UTC = 01:00:00 EDT 0
06:00:00 UTC = 01:00:00 EST 1
07:00:00 UTC = 02:00:00 EST 0
fold 属性的值对于所有实例都具有 0
值,但在不明确的情况下表示第二个(按时间顺序)时刻的实例除外。
PEP 529:将 Windows 文件系统编码更改为 UTF-8
最好使用 str (Unicode) 而不是字节来表示文件系统路径。 但是,在某些情况下,使用字节就足够且正确。
在 Python 3.6 之前,在 Windows 上使用字节路径时可能会导致数据丢失。 通过此更改,Windows 现在支持使用字节来表示路径,前提是这些字节使用 sys.getfilesystemencoding() 返回的编码进行编码,现在默认为 'utf-8'
。
不使用 str 来表示路径的应用程序应该使用 os.fsencode() 和 os.fsdecode() 来确保它们的字节被正确编码。 要恢复以前的行为,请设置 PYTHONLEGACYWINDOWSFSENCODING 或调用 sys._enablelegacywindowsfsencoding()。
有关可能需要的代码修改的更多信息和讨论,请参阅 PEP 529。
PEP 528:将 Windows 控制台编码更改为 UTF-8
Windows 上的默认控制台现在将接受所有 Unicode 字符,并向 Python 代码提供正确读取的 str 对象。 sys.stdin
、sys.stdout
和 sys.stderr
现在默认为 utf-8 编码。
此更改仅适用于使用交互式控制台时,而不适用于重定向文件或管道时。 要恢复到以前的交互控制台使用行为,请设置 PYTHONLEGACYWINDOWSSTDIO。
PEP 520:保留类属性定义顺序
类定义主体中的属性具有自然顺序:名称在源中出现的顺序相同。 此顺序现在保留在新类的 __dict__ 属性中。
此外,有效的默认类 execution 命名空间(从 type.__prepare__() 返回)现在是一个插入顺序保留映射。
新的 dict 实现
dict 类型现在使用基于 由 Raymond Hettinger 提出的提议的“紧凑”表示,该提议 首先由 PyPy 实现。 与 Python 3.5 相比,新的 dict() 的内存使用量减少了 20% 到 25%。
这个新实现的顺序保留方面被认为是一个实现细节,不应依赖(这可能会在未来发生变化,但在更改语言规范之前,希望在几个版本的语言中使用这个新的 dict 实现为所有当前和未来的 Python 实现强制要求保持顺序的语义;这也有助于保持与旧版本语言的向后兼容性,其中随机迭代顺序仍然有效,例如 Python 3.5)。
(由稻田直树在 中提供:issue:`27350`。 想法 最初由 Raymond Hettinger 建议。)
PEP 523:向 CPython 添加框架评估 API
虽然 Python 为自定义代码的执行方式提供了广泛的支持,但它没有这样做的一个地方是在框架对象的评估中。 如果您想要某种方法来拦截 Python 中的帧评估,那么如果不直接操作已定义函数的函数指针,真的没有任何办法。
PEP 523 通过提供 API 使框架评估在 C 级别可插入来改变这一点。 这将允许调试器和 JIT 等工具在 Python 代码开始执行之前拦截帧评估。 这使得可以使用 Python 代码的替代评估实现、跟踪框架评估等。
此 API 不是受限 C API 的一部分,并被标记为私有以表示此 API 的使用预计将受到限制,并且仅适用于非常精选的低级用例。 API 的语义将根据需要随 Python 更改。
PYTHONMALLOC 环境变量
新的 PYTHONMALLOC 环境变量允许设置 Python 内存分配器和安装调试钩子。
现在可以在使用 PYTHONMALLOC=debug
以发布模式编译的 Python 上的 Python 内存分配器上安装调试挂钩。 调试钩子的作用:
- 新分配的内存用字节
0xCB
填充 - 释放的内存填充字节
0xDB
- 检测违反 Python 内存分配器 API 的情况。 例如,PyObject_Free() 在由 PyMem_Malloc() 分配的内存块上调用。
- 在缓冲区开始之前检测写入(缓冲区下溢)
- 检测缓冲区结束后的写入(缓冲区溢出)
- 检查
PYMEM_DOMAIN_OBJ
(例如:PyObject_Malloc())和PYMEM_DOMAIN_MEM
(例如:PyMem_Malloc( )) 域被调用。
检查 GIL 是否被持有也是 Python 3.6 的一个新特性。
有关 Python 内存分配器的调试挂钩,请参阅 PyMem_SetupDebugHooks() 函数。
现在还可以使用 PYTHONMALLOC=malloc
强制使用 C 库的 malloc()
分配器进行所有 Python 内存分配。 当在以发布模式编译的 Python 上使用 Valgrind 等外部内存调试器时,这很有用。
出错时,Python 内存分配器上的调试挂钩现在使用 tracemalloc 模块来获取分配内存块的回溯。
使用 python3.6 -X tracemalloc=5
的缓冲区溢出致命错误示例(在跟踪中存储 5 帧):
Debug memory block at address p=0x7fbcd41666f8: API 'o'
4 bytes originally requested
The 7 pad bytes at p-7 are FORBIDDENBYTE, as expected.
The 8 pad bytes at tail=0x7fbcd41666fc are not all FORBIDDENBYTE (0xfb):
at tail+0: 0x02 *** OUCH
at tail+1: 0xfb
at tail+2: 0xfb
at tail+3: 0xfb
at tail+4: 0xfb
at tail+5: 0xfb
at tail+6: 0xfb
at tail+7: 0xfb
The block was made by call #1233329 to debug malloc/realloc.
Data at p: 1a 2b 30 00
Memory block allocated at (most recent call first):
File "test/test_bytes.py", line 323
File "unittest/case.py", line 600
File "unittest/case.py", line 648
File "unittest/suite.py", line 122
File "unittest/suite.py", line 84
Fatal Python error: bad trailing pad byte
Current thread 0x00007fbcdbd32700 (most recent call first):
File "test/test_bytes.py", line 323 in test_hex
File "unittest/case.py", line 600 in run
File "unittest/case.py", line 648 in __call__
File "unittest/suite.py", line 122 in run
File "unittest/suite.py", line 84 in __call__
File "unittest/suite.py", line 122 in run
File "unittest/suite.py", line 84 in __call__
...
(由 Victor Stinner 在 :issue:`26516` 和 :issue:`26564` 中贡献。)
DTrace 和 SystemTap 探测支持
现在可以构建 Python --with-dtrace
,它为解释器中的以下事件启用静态标记:
- 函数调用/返回
- 垃圾收集开始/完成
- 执行的代码行。
这可用于在生产中检测正在运行的解释器,而无需重新编译特定的调试版本或提供特定于应用程序的分析/调试代码。
使用 DTrace 和 SystemTap 检测 CPython 中的更多详细信息。
当前的实现在 Linux 和 macOS 上进行了测试。 将来可能会添加其他标记。
(由 Łukasz Langa 在 :issue:`21590` 中贡献,基于 Jesús Cea Avión、David Malcolm 和 Nikhil Benesch 的补丁。)
其他语言更改
对核心 Python 语言进行的一些较小更改是:
global
或nonlocal
语句现在必须在同一范围内第一次使用受影响的名称之前以文本形式出现。 以前这是一个 SyntaxWarning。- 现在可以将特殊方法设置为
None
以指示相应操作不可用。 例如,如果一个类将__iter__()
设置为None
,则该类不可迭代。 (由 Andrew Barnert 和 Ivan Levkivskyi 在 :issue:`25958` 中提供。) - 重复回溯行的长序列现在缩写为
"[Previous line repeated {count} more times]"
(参见 traceback 示例)。 (由 Emanuel Barry 在 中提供:issue:`26823`。) - 当导入找不到模块时,现在会引发新的异常 ModuleNotFoundError(ImportError 的子类)。 当前检查 ImportError 的代码(在 try-except 中)仍然可以工作。 (由 Eric Snow 在 中贡献:问题:`15767`。)
- 在类创建期间从元类方法调用时,依赖零参数
super()
的类方法现在可以正常工作。 (由 Martin Teichmann 在 中提供:issue:`23722`。)
新模块
秘密
新的 secrets 模块的主要目的是提供一种明显的方法来可靠地生成适用于管理机密的加密强伪随机值,例如帐户身份验证、令牌等。
警告
请注意,random 模块中的伪随机生成器应该 NOT 用于安全目的。 在 Python 3.6+ 上使用 secrets,在 Python 3.5 及更早版本上使用 os.urandom()。
改进的模块
异步
从 Python 3.6 开始,asyncio
模块不再是临时的,它的 API 被认为是稳定的。
自 Python 3.5.0 以来 asyncio 模块的显着变化(由于临时状态,全部向后移植到 3.5.x):
- get_event_loop() 函数已更改为从协程和回调调用时始终返回当前运行的循环。 (由 Yury Selivanov 在 中提供:issue:`28613`。)
- ensure_future() 函数和所有使用它的函数,例如 loop.run_until_complete(),现在接受各种 awaitable 对象 。 (由尤里·塞利瓦诺夫提供。)
- 新的 run_coroutine_threadsafe() 函数将协程提交给来自其他线程的事件循环。 (文森特·米歇尔供稿。)
- 新的 Transport.is_closure() 方法来检查传输是关闭还是关闭。 (由尤里·塞利瓦诺夫提供。)
loop.create_server()
方法现在可以接受主机列表。 (由 Yann Sionneau 提供。)- 新的 loop.create_future() 方法来创建 Future 对象。 这允许替代事件循环实现,例如 uvloop,以提供更快的 asyncio.Future 实现。 (由 Yury Selivanov 在 中提供:issue:`27041`。)
- 新的 loop.get_exception_handler() 方法来获取当前异常处理程序。 (由 Yury Selivanov 在 中提供:issue:`27040`。)
- 新的
StreamReader.readuntil()
方法从流中读取数据,直到出现分隔符字节序列。 (马克·科伦伯格供稿。) StreamReader.readexactly()
的性能得到提升。 (由 Mark Korenberg 在 :issue:`28370` 中提供。)- 优化了
loop.getaddrinfo()
方法,避免在地址已经解析的情况下调用系统getaddrinfo
函数。 (由 A. 杰西·吉留·戴维斯。) - loop.stop() 方法已更改为在当前迭代后立即停止循环。 由于上次迭代而安排的任何新回调都将被丢弃。 (由 Guido van Rossum 在 中提供:issue:`25593`。)
Future.set_exception
现在将在传递 StopIteration 异常实例时引发 TypeError。 (由 Chris Angelico 在 中提供:issue:`26221`。)- 新的
loop.connect_accepted_socket()
方法供接受 asyncio 外部连接但使用 asyncio 处理它们的服务器使用。 (由 Jim Fulton 在 中提供:issue:`27392`。) TCP_NODELAY
标志现在默认为所有 TCP 传输设置。 (由 Yury Selivanov 在 :issue:`27456` 中贡献。)- 新的
loop.shutdown_asyncgens()
可在关闭回路之前正确关闭待处理的异步发电机。 (由 Yury Selivanov 在 :issue:`28003` 中贡献。) - Future 和 Task 类现在有一个优化的 C 实现,使异步代码高达 30% faster。 (由 Yury Selivanov 和 INADA Naoki 在 :issue:`26081` 和 :issue:`28544` 中贡献。)
数学
添加了新的 cmath.tau (τ) 常数。 (由 Lisa Roach 在 中提供:issue:`12345`,详情参见 PEP 628。)
新常量:cmath.inf 和 cmath.nan 以匹配 math.inf 和 math.nan,以及 cmath .infj 和 cmath.nanj 以匹配复杂代表使用的格式。 (由 Mark Dickinson 在 :issue:`23229` 中贡献。)
收藏
添加了新的 Collection 抽象基类以表示大小的可迭代容器类。 (由 Ivan Levkivskyi 提供,Neil Girdhar 在 :issue:`27598` 中提供的文档。)
新的 Reversible 抽象基类表示也提供 __reversed__()
方法的可迭代类。 (由 Ivan Levkivskyi 在 :issue:`25987` 中贡献。)
新的 AsyncGenerator 抽象基类代表异步生成器。 (由 Yury Selivanov 在 中提供:issue:`28720`。)
namedtuple() 函数现在接受一个可选的关键字参数 module,当指定时,它用于返回的命名元组类的 __module__
属性。 (由 Raymond Hettinger 在 中提供:issue:`17941`。)
namedtuple() 的 verbose 和 rename 参数现在只有关键字。 (由 Raymond Hettinger 在 中提供:issue:`25628`。)
现在可以腌制递归 collections.deque 实例。 (由 Serhiy Storchaka 在 中提供:issue:`26482`。)
并发期货
ThreadPoolExecutor 类构造函数现在接受一个可选的 thread_name_prefix 参数,以便可以自定义池创建的线程的名称。 (由格雷戈里 P. 中的史密斯:问题:`27664`。)
上下文库
添加了 contextlib.AbstractContextManager 类来为上下文管理器提供抽象基类。 它为 __enter__() 提供了一个合理的默认实现,它返回 self
并留下 __exit__() 一个抽象方法。 匹配类已添加到 typing 模块作为 typing.ContextManager。 (由 Brett Cannon 在 中提供:issue:`25609`。)
约会时间
datetime 和 time 类具有新的 fold
属性,用于在必要时消除本地时间的歧义。 datetime 中的许多函数已更新以支持本地时间消歧。 有关更多信息,请参阅 本地时间消歧 部分。 (由 Alexander Belopolsky 在 :issue:`24773` 中提供。)
datetime.strftime() 和 date.strftime() 方法现在支持 ISO 8601 日期指令 %G
、%u
和 %V
]。 (由 Ashley Anderson 在 :issue:`12006` 中提供。)
datetime.isoformat() 函数现在接受一个可选的 timespec 参数,该参数指定要包含的时间值的附加组件的数量。 (由 Alessandro Cucci 和 Alexander Belopolsky 在 :issue:`19475` 中提供。)
datetime.combine() 现在接受一个可选的 tzinfo 参数。 (由 Alexander Belopolsky 在 :issue:`27661` 中贡献。)
十进制
新的 Decimal.as_integer_ratio() 方法返回一对 (n, d)
整数,这些整数将给定的 Decimal 实例表示为一个分数,以最低项和正分母表示:
>>> Decimal('-3.14').as_integer_ratio()
(-157, 50)
(由 Stefan Krah 和 Mark Dickinson 在 中提供:issue:`25928`。)
分配器
default_format
属性已从 distutils.command.sdist.sdist
中移除,formats
属性默认为 ['gztar']
。 尽管没有预料到,任何依赖于 default_format
存在的代码都可能需要进行调整。 有关更多详细信息,请参阅 :issue:`27819`。
电子邮件
通过 policy 关键字为各种构造函数启用的新电子邮件 API 不再是临时的。 email 文档已经过重新组织和重写,以专注于新 API,同时保留旧 API 的旧文档。 (由 R. 中的 David Murray:问题:`24277`。)
email.mime 类现在都接受可选的 policy 关键字。 (由 Berker Peksag 在 中提供:issue:`27331`。)
DecodedGenerator 现在支持 policy 关键字。
有一个新的 policy 属性,message_factory,它控制解析器创建新消息对象时默认使用的类。 对于 email.policy.compat32 策略,这是 Message,对于新策略,它是 EmailMessage。 (由 R. 中的 David Murray:问题:`20476`。)
编码
在 Windows 上,添加了 'oem'
编码以使用 CP_OEMCP
,以及现有 'mbcs'
编码的 'ansi'
别名,使用 CP_ACP
代码页。 (由 Steve Dower 在 中提供:issue:`27959`。)
枚举
enum 模块中添加了两个新的枚举基类:Flag 和 IntFlags
。 两者都用于定义可以使用按位运算符组合的常量。 (由 Ethan Furman 在 中提供:issue:`23591`。)
许多标准库模块已更新为使用 IntFlags
类作为其常量。
新的 enum.auto 值可用于自动为枚举成员赋值:
>>> from enum import Enum, auto
>>> class Color(Enum):
... red = auto()
... blue = auto()
... green = auto()
...
>>> list(Color)
[<Color.red: 1>, <Color.blue: 2>, <Color.green: 3>]
故障处理程序
在 Windows 上,faulthandler 模块现在为 Windows 异常安装一个处理程序:参见 faulthandler.enable()。 (由 Victor Stinner 在 中提供:问题:`23848`。)
哈希库
hashlib 支持 OpenSSL 1.1.0。 最低推荐版本为 1.0.2。 (由 Christian Heimes 在 中提供:issue:`26470`。)
BLAKE2 哈希函数已添加到模块中。 blake2b() 和 blake2s() 始终可用并支持 BLAKE2 的完整功能集。 (由 Christian Heimes 在 中贡献:issue:`26798` 基于 Dmitry Chestnykh 和 Samuel Neves 的代码。 文档由 Dmitry Chestnykh 编写。)
SHA-3 哈希函数 sha3_224()
、sha3_256()
、sha3_384()
、sha3_512()
和 SHAKE 哈希函数 shake_128()
和 shake_256()
] 添加。 (由 Christian Heimes 在 中提供:issue:`16113`。 Keccak 代码包由 Guido Bertoni、Joan Daemen、Michaël Peeters、Gilles Van Assche 和 Ronny Van Keer 编写。)
基于密码的密钥派生函数 scrypt() 现在可用于 OpenSSL 1.1.0 和更新版本。 (由 Christian Heimes 在 中提供:issue:`27928`。)
客户端
HTTPConnection.request() 和 endheaders() 现在都支持分块编码请求正文。 (由 Demian Brecht 和 Rolf Krahl 在 :issue:`12319` 中提供。)
空闲库和空闲
idlelib 包正在进行现代化和重构,以使 IDLE 的外观和工作更好,并使代码更易于理解、测试和改进。 使 IDLE 看起来更好的部分原因,尤其是在 Linux 和 Mac 上,是使用 ttk 小部件,主要是在对话框中。 因此,IDLE 不再与 tcl/tk 8.4 一起运行。 它现在需要 tcl/tk 8.5 或 8.6。 我们建议运行两者的最新版本。
“现代化”包括重命名和整合 idlelib 模块。 部分大写文件的重命名类似于将 Tkinter 和 TkFont 重命名为 3.0 中的 tkinter 和 tkinter.font。 因此,在 3.5 中工作的 idlelib 文件的导入通常在 3.6 中不起作用。 至少需要更改模块名称(参见 idlelib/README.txt),有时更多。 (由 Al Swiegart 和 Terry Reedy 在 :issue:`24225` 中贡献的名称更改。 此后的大多数 idlelib 补丁已经并将成为该过程的一部分。)
作为补偿,最终的结果是一些 idlelib 类将更容易使用,有更好的 API 和文档字符串来解释它们。 其他有用的信息将在可用时添加到 idlelib。
3.6.2 中的新功能:
自动完成的多项修复。 (由 Louie Lu 在 中提供:issue:`15786`。)
3.6.3 中的新功能:
模块浏览器(在文件菜单上,以前称为类浏览器)现在除了显示顶级函数和类之外,还显示嵌套的函数和类。 (由 Guilherme Polo、Cheryl Sabella 和 Terry Jan Reedy 在 :issue:`1612262` 中提供。)
以前作为扩展实现的 IDLE 功能已重新实现为普通功能。 它们的设置已从“扩展”选项卡移至其他对话框选项卡。 (由 Charles Wohlganger 和 Terry Jan Reedy 在 :issue:`27099` 中提供。)
设置对话框(选项、配置空闲)已部分重写以改进外观和功能。 (由 Cheryl Sabella 和 Terry Jan Reedy 在多个问题中提供。)
3.6.4 中的新功能:
字体示例现在包括一系列非拉丁字符,以便用户可以更好地看到选择特定字体的效果。 (由 Terry Jan Reedy 在 中贡献:issue:`13802`。)可以编辑示例以包含其他字符。 (由 Serhiy Storchaka 在 中提供:issue:`31860`。)
3.6.6 中的新功能:
修改了编辑器代码上下文选项。 Box 显示所有上下文行直到 maxlines。 单击上下文行会将编辑器跳转到该行。 自定义主题的上下文颜色添加到“设置”对话框的“亮点”选项卡中。 (由 Cheryl Sabella 和 Terry Jan Reedy 在 :issue:`33642`、:issue:`33768` 和 :issue:`33679` 中贡献。 )
在 Windows 上,一个新的 API 调用告诉 Windows tk 针对 DPI 进行缩放。 在 Windows 8.1+ 或 10 上,Python 二进制文件的 DPI 兼容性属性保持不变,并且显示器分辨率大于 96 DPI,这应该会使文本和线条更清晰。 否则它应该没有任何影响。 (由 Terry Jan Reedy 在 :issue:`33656` 中提供。)
3.6.7 中的新功能:
N 行(默认为 50)的输出被压缩到一个按钮。 N 可以在 Settings 对话框的 General 页面的 PyShell 部分中更改。 右键单击输出可以压缩更少但可能超长的行。 可以通过双击按钮或右键单击按钮将压缩的输出扩展到剪贴板或单独的窗口。 (由 Tal Einat 在 中提供:问题:`1529353`。)
导入库
当导入找不到模块时,现在会引发新的异常 ModuleNotFoundError(ImportError 的子类)。 当前检查 ImportError
(在 try-except 中)的代码仍然有效。 (由 Eric Snow 在 中贡献:问题:`15767`。)
importlib.util.LazyLoader 现在在包装好的加载器上调用 create_module(),取消了 importlib.machinery.BuiltinImporter 和 importlib.machinery 的限制。 ExtensionFileLoader 不能与 importlib.util.LazyLoader 一起使用。
importlib.util.cache_from_source()、importlib.util.source_from_cache() 和 importlib.util.spec_from_file_location() 现在接受 路径-像对象。
检查
inspect.signature() 函数现在报告编译器为理解和生成器表达式范围生成的隐式 .0
参数,就好像它们是名为 implicit0
的仅位置参数。 (由 Jelle Zijlstra 在 :issue:`19611` 中提供。)
为了减少从 Python 2.7 和旧的 inspect.getargspec() API 升级时的代码改动,先前记录的 inspect.getfullargspec() 已被取消。 虽然此函数对于单一/源 Python 2/3 代码库很方便,但更丰富的 inspect.signature() 接口仍然是推荐的新代码方法。 (由 Nick Coghlan 在 中提供:issue:`27172`)
json
json.load() 和 json.loads() 现在支持二进制输入。 编码的 JSON 应使用 UTF-8、UTF-16 或 UTF-32 表示。 (由 Serhiy Storchaka 在 中提供:issue:`17909`。)
日志记录
添加了新的 WatchedFileHandler.reopenIfNeeded() 方法以添加检查是否需要重新打开日志文件的功能。 (由 Marian Horban 在 中提供:issue:`24884`。)
操作系统
有关 os 和 os.path 模块现在如何支持 path-like objects 的详细信息,请参阅 PEP 519 的摘要。
scandir() 现在支持 Windows 上的 bytes 路径。
新的 close() 方法允许显式关闭 scandir() 迭代器。 scandir() 迭代器现在支持 上下文管理器 协议。 如果 scandir()
迭代器既未耗尽也未明确关闭,则 ResourceWarning 将在其析构函数中发出。 (由 Serhiy Storchaka 在 中提供:issue:`25994`。)
在 Linux 上,os.urandom() 现在会阻塞,直到系统 urandom 熵池初始化以提高安全性。 有关基本原理,请参阅 PEP 524。
Linux getrandom()
系统调用(获取随机字节)现在公开为新的 os.getrandom() 函数。 (由 Victor Stinner 提供,PEP 524 的一部分)
泡菜
需要使用关键字参数调用 __new__
的对象现在可以使用早于协议版本 4 的 pickle 协议 进行pickle。 协议版本 4 已经支持这种情况。 (由 Serhiy Storchaka 在 中提供:issue:`24164`。)
pydoc
pydoc 模块已经学会尊重 MANPAGER
环境变量。 (由 Matthias Klose 在 :issue:`8637` 中贡献。)
help() 和 pydoc 现在可以按定义的顺序而不是按字母顺序列出命名的元组字段。 (由 Raymond Hettinger 在 中提供:issue:`24879`。)
关于
在正则表达式中添加了对修饰符跨度的支持。 示例:'(?i:p)ython'
匹配 'python'
和 'Python'
,但不匹配 'PYTHON'
; '(?i)g(?-i:v)r'
匹配 'GvR'
和 'gvr'
,但不匹配 'GVR'
。 (由 Serhiy Storchaka 在 中提供:issue:`433028`。)
匹配对象组可以通过 __getitem__
访问,相当于 group()
。 所以 mo['name']
现在等同于 mo.group('name')
。 (由 Eric Smith 在 :issue:`24454` 中提供。)
Match
对象现在支持 [X30X] 类索引对象 作为组索引。 (由 Jeroen Demeyer 和 Zhang 在 中提供:issue:`27177`。)
完成者
现在省略私有和特殊属性名称,除非前缀以下划线开头。 在一些完整的关键字之后添加一个空格或冒号。 (由 Serhiy Storchaka 在 :issue:`25011` 和 :issue:`25209` 中贡献。)
shlex
shlex 通过新的 punctuation_chars 参数来控制哪些字符被视为标点符号,改进了外壳兼容性。 (由 Vinay Sajip 在 中提供:issue:`1521950`。)
地点
在 .pth 文件中指定要添加到 sys.path 的路径时,您现在可以在目录顶部指定文件路径(例如 压缩文件)。 (由 Wolfgang Langner 在 :issue:`26587` 中贡献)。
插座
ioctl() 函数现在支持 SIO_LOOPBACK_FAST_PATH 控制代码。 (由 Daniel Stokes 在 :issue:`26536` 中提供。)
现在支持 getsockopt() 常量 SO_DOMAIN
、SO_PROTOCOL
、SO_PEERSEC
和 SO_PASSSEC
。 (由 Christian Heimes 在 中提供:issue:`26907`。)
setsockopt() 现在支持 setsockopt(level, optname, None, optlen: int)
形式。 (由 Christian Heimes 在 中提供:issue:`27744`。)
套接字模块现在支持地址族 AF_ALG 与 Linux 内核加密 API 接口。 添加了 ALG_*
、SOL_ALG
和 sendmsg_afalg()。 (由 Christian Heimes 在 :issue:`27744` 中提供,并得到 Victor Stinner 的支持。)
添加了新的 Linux 常量 TCP_USER_TIMEOUT
和 TCP_CONGESTION
。 (由 Omar Sandoval 提供,问题:26273)。
套接字服务器
基于socketserver模块的服务器,包括在http.server、xmlrpc.server和wsgiref.simple_server中定义的服务器,现在支持上下文管理器协议。 (由 Aviv Palivoda 在 中提供:issue:`26404`。)
StreamRequestHandler 类的 wfile
属性现在实现了 io.BufferedIOBase 可写接口。 特别是,现在可以保证调用 write() 来完整发送数据。 (由 Martin Panter 在 中提供:issue:`26721`。)
ssl
ssl 支持 OpenSSL 1.1.0。 最低推荐版本为 1.0.2。 (由 Christian Heimes 在 中提供:issue:`26470`。)
3DES 已从默认密码套件中删除,并添加了 ChaCha20 Poly1305 密码套件。 (由 Christian Heimes 在 :issue:`27850` 和 :issue:`27766` 中贡献。)
SSLContext 对选项和密码有更好的默认配置。 (由 Christian Heimes 在 中提供:issue:`28043`。)
可以使用新的 SSLSession 类将 SSL 会话从一个客户端连接复制到另一个客户端连接。 TLS 会话恢复可以加速初始握手,减少延迟并提高性能(由 Christian Heimes 在 中贡献:issue:`19500` 基于 Alex Warhawk 的草稿。)
新的 get_ciphers() 方法可用于按密码优先级获取已启用密码的列表。
所有常量和标志都已转换为 IntEnum 和 IntFlags
。 (由 Christian Heimes 在 中提供:issue:`28025`。)
添加了用于 SSLContext 的服务器和客户端特定 TLS 协议。 (由 Christian Heimes 在 中提供:issue:`28085`。)
子流程
subprocess.Popen 析构函数现在在子进程仍在运行时发出 ResourceWarning 警告。 使用上下文管理器协议(with proc: ...
)或显式调用wait()方法来读取子进程的退出状态。 (由 Victor Stinner 在 中提供:问题:`26741`。)
subprocess.Popen 构造函数和所有传递参数的函数现在接受 encoding 和 errors 参数。 指定其中之一将为 stdin、stdout 和 stderr 流启用文本模式。 (由 Steve Dower 在 中提供:issue:`6135`。)
系统
新的 getfilesystemencodeerrors() 函数返回用于在 Unicode 文件名和字节文件名之间转换的错误模式的名称。 (由 Steve Dower 在 中提供:issue:`27781`。)
在 Windows 上,getwindowsversion() 函数的返回值现在包括 platform_version 字段,其中包含当前操作系统的准确主要版本、次要版本和内部版本号,而不是版本正在为该过程模拟(由 Steve Dower 在 :issue:`27932` 中贡献。)
时间
添加了新的 Timer.autorange() 便捷方法,以重复调用 Timer.timeit() 使总运行时间大于或等于 200 毫秒。 (由 Steven D'Aprano 在 :issue:`6422` 中提供。)
timeit 现在在最佳时间和最坏时间之间存在显着 (4x) 差异时发出警告。 (由 Serhiy Storchaka 在 中提供:issue:`23552`。)
特金特
在 tkinter.Variable
类中添加了方法 trace_add()
、trace_remove()
和 trace_info()
。 它们替换了旧方法 trace_variable()
、trace()
、trace_vdelete()
和 trace_vinfo()
,这些方法使用过时的 Tcl 命令并且可能在未来版本的 Tcl 中不起作用。 (由 Serhiy Storchaka 在 :issue:`22115` 中贡献)。
追溯
回溯模块和解释器的内置异常显示现在都缩写回溯中重复行的长序列,如以下示例所示:
>>> def f(): f()
...
>>> f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in f
File "<stdin>", line 1, in f
File "<stdin>", line 1, in f
[Previous line repeated 995 more times]
RecursionError: maximum recursion depth exceeded
(由 Emanuel Barry 在 中提供:issue:`26823`。)
tracemalloc
tracemalloc 模块现在支持跟踪多个不同地址空间中的内存分配。
添加了新的 DomainFilter 过滤器类,以按地址空间(域)过滤块跟踪。
(由 Victor Stinner 在 中提供:问题:`26588`。)
打字
由于 typing 模块是 临时 ,Python 3.6 中引入的所有更改也已向后移植到 Python 3.5.x。
typing 模块大大改进了对泛型类型别名的支持。 例如 Dict[str, Tuple[S, T]]
现在是一个有效的类型注释。 (由 Guido van Rossum 在 Github #195 中提供。)
添加了 typing.ContextManager 类来表示 contextlib.AbstractContextManager。 (由 Brett Cannon 在 中提供:issue:`25609`。)
添加了 typing.Collection 类来表示 collections.abc.Collection。 (由 Ivan Levkivskyi 在 :issue:`27598` 中贡献。)
添加了 typing.ClassVar 类型构造以标记类变量。 正如在 PEP 526 中所介绍的,ClassVar 中包装的变量注释表示给定的属性旨在用作类变量,不应在该类的实例上设置。 (由 Ivan Levkivskyi 在 Github #280 中贡献。)
一个新的 TYPE_CHECKING 常量,静态类型检查器假定该常量为 True
,但在运行时为 False
。 (由 Guido van Rossum 在 Github #230 中提供。)
添加了一个新的 NewType() 辅助函数来为注释创建轻量级的不同类型:
from typing import NewType
UserId = NewType('UserId', int)
some_id = UserId(524313)
静态类型检查器会将新类型视为原始类型的子类。 (由 Ivan Levkivskyi 在 Github #189 中贡献。)
单元测试.mock
Mock 类有以下改进:
- 两个新方法 Mock.assert_called() 和 Mock.assert_Called_once() 来检查是否调用了模拟对象。 (由 Amit Saha 在 中提供:issue:`26323`。)
- Mock.reset_mock() 方法现在有两个可选的仅关键字参数:return_value 和 side_effect。 (由 Kushal Das 在 中提供:issue:`21271`。)
urllib.request
如果 HTTP 请求具有文件或可迭代主体(字节对象除外)但没有 Content-Length
标头,而不是抛出错误,AbstractHTTPHandler
现在回退到使用分块传输编码。 (由 Demian Brecht 和 Rolf Krahl 在 :issue:`12319` 中提供。)
urllib.robotparser
RobotFileParser 现在支持 Crawl-delay
和 Request-rate
扩展。 (由 Nikolay Bogoychev 在 :issue:`16099` 中提供。)
venv
venv 接受一个新参数 --prompt
。 此参数为虚拟环境提供替代前缀。 (由 Łukasz Balcerzak 提出并由 Stéphane Wirtel 在 :issue:`22829` 中移植到 3.6。)
警告
一个新的可选 source 参数已添加到 warnings.warn_explicit() 函数:发出 ResourceWarning 的销毁对象。 source 属性也已添加到 warnings.WarningMessage
(由 Victor Stinner 在 :issue:`26568` 和 :issue:`26567` 中贡献])。
当记录 ResourceWarning 警告时,tracemalloc 模块现在用于尝试检索分配已销毁对象的回溯。
脚本 example.py
示例:
import warnings
def func():
return open(__file__)
f = func()
f = None
命令 python3.6 -Wd -X tracemalloc=5 example.py
的输出:
example.py:7: ResourceWarning: unclosed file <_io.TextIOWrapper name='example.py' mode='r' encoding='UTF-8'>
f = None
Object allocated at (most recent call first):
File "example.py", lineno 4
return open(__file__)
File "example.py", lineno 6
f = func()
“对象分配于”回溯是新的,只有在 tracemalloc 正在跟踪 Python 内存分配并且已经导入 warnings 模块时才会显示。
客户端
xmlrpc.client 模块现在支持解组由 Apache XML-RPC 实现用于数字和 None
的附加数据类型。 (由 Serhiy Storchaka 在 中提供:issue:`26885`。)
压缩文件
新的 ZipInfo.from_file() 类方法允许从文件系统文件创建 ZipInfo 实例。 新的 ZipInfo.is_dir() 方法可用于检查 ZipInfo 实例是否表示目录。 (由 Thomas Kluyver 在 :issue:`26039` 中贡献。)
ZipFile.open() 方法现在可用于将数据写入 ZIP 文件以及提取数据。 (由 Thomas Kluyver 在 :issue:`26039` 中贡献。)
zlib
compress() 和 decompress() 函数现在接受关键字参数。 (分别由 :issue:`26243` 中的 Aviv Palivoda 和 :issue:`16764` 中的 Zhang Zhang 贡献。)
优化
- Python 解释器现在使用 16 位字码而不是字节码,这使得许多操作码优化成为可能。 (由 Demur Rumed 在 :issue:`26647` 和 :issue:`28050` 中提供了来自 Serhiy Storchaka 和 Victor Stinner 的意见和评论。)
- asyncio.Future 类现在有一个优化的 C 实现。 (由 Yury Selivanov 和 INADA Naoki 在 中提供:issue:`26081`。)
- asyncio.Task 类现在有一个优化的 C 实现。 (由 Yury Selivanov 在 :issue:`28544` 中贡献。)
- typing 模块中的各种实现改进(例如泛型类型的缓存)最多可将性能提升 30 倍并减少内存占用。
- ASCII 解码器现在对于错误处理程序
surrogateescape
、ignore
和replace
的速度提高了 60 倍(由 Victor Stinner 在 中贡献:问题:`24870`[ X154X])。 - 对于错误处理程序
surrogateescape
(由 Victor Stinner 在 :issue:`25227` 中贡献),ASCII 和 Latin1 编码器现在最多快 3 倍。 - UTF-8 编码器现在对于错误处理程序
ignore
、replace
、surrogateescape
、surrogatepass
的速度提高了 75 倍(由 Victor Stinner 在 [ X144X]:问题:`25267`)。 - UTF-8 解码器现在对于错误处理程序
ignore
、replace
和surrogateescape
的速度提高了 15 倍(由 Victor Stinner 在 中贡献:issue:`25301 `)。 bytes % args
现在最多快 2 倍。 (由 Victor Stinner 在 :issue:`25349` 中提供)。bytearray % args
现在快了 2.5 到 5 倍。 (由 Victor Stinner 在 :issue:`25399` 中提供)。- 优化 bytes.fromhex() 和 bytearray.fromhex():它们现在的速度提高了 2 到 3.5 倍。 (由 Victor Stinner 在 :issue:`25401` 中提供)。
- 优化
bytes.replace(b, b'.')
和bytearray.replace(b
, b'.')
:最高 80% faster。 (由 Josh Snider 在 :issue:`26574` 中贡献)。 - PyMem_Malloc() 域 (
PYMEM_DOMAIN_MEM
) 的分配器函数现在使用 pymalloc 内存分配器 而不是 C 库的malloc()
函数。 pymalloc 分配器针对小于或等于 512 字节且生命周期较短的对象进行了优化,并针对较大的内存块使用malloc()
。 (由 Victor Stinner 在 :issue:`26249` 中提供)。 - pickle.load() 和 pickle.loads() 现在在反序列化许多小对象时高达 10% faster(由 Victor Stinner 在 中贡献:问题:` 27056`)。
- 与传递 位置参数 相比,将 关键字参数 传递给函数具有开销。 现在,在使用 Argument Clinic 实现的扩展函数中,这种开销显着减少。 (由 Serhiy Storchaka 在 :issue:`27574` 中贡献)。
- 优化 glob 模块中的 glob() 和 iglob() 函数; 他们现在大约快 3-6 倍。 (由 Serhiy Storchaka 在 :issue:`25596` 中贡献)。
- 使用 os.scandir() 优化 pathlib 中的 globbing; 现在大约快 1.5-4 倍。 (由 Serhiy Storchaka 在 :issue:`26032` 中贡献)。
- xml.etree.ElementTree 解析、迭代和深拷贝性能得到显着提升。 (由 Serhiy Storchaka 在 :issue:`25638`、:issue:`25873` 和 :issue:`25869` 中贡献。)
- 从浮点数和小数点创建 fractions.Fraction 实例现在快了 2 到 3 倍。 (由 Serhiy Storchaka 在 中提供:issue:`25971`。)
构建和 C API 更改
- Python 现在需要工具链中的一些 C99 支持才能构建。 最值得注意的是,Python 现在使用标准整数类型和宏来代替像
PY_LONG_LONG
这样的自定义宏。 有关更多信息,请参阅 PEP 7 和 :issue:`17884`。 - 使用 Android NDK 和 Android API 级别设置为 21 (Android 5.0 Lollipop) 或更高版本的交叉编译 CPython 成功运行。 虽然 Android 还不是受支持的平台,但 Python 测试套件在 Android 模拟器上运行时只有大约 16 次测试失败。 请参阅 Android 元问题 :issue:`26865`。
- 添加了
--enable-optimizations
配置标志。 打开它会激活昂贵的优化,如 PGO。 (英特尔的 Alecsandru Patrascu 在 中的原始补丁:问题:`26359`。) - GIL 现在必须在
PYMEM_DOMAIN_OBJ
(例如:PyObject_Malloc())和PYMEM_DOMAIN_MEM
(例如:PyMem_Malloc( )) 域被调用。 - 新的 Py_FinalizeEx() API 指示刷新缓冲数据是否失败。 (由 Martin Panter 在 :issue:`5319` 中提供。)
- PyArg_ParseTupleAndKeywords() 现在支持 仅位置参数 。 仅位置参数由空名称定义。 (由 Serhiy Storchaka 在 :issue:`26282` 中贡献)。
PyTraceback_Print
方法现在将重复行的长序列缩写为"[Previous line repeated {count} more times]"
。 (由 Emanuel Barry 在 中提供:issue:`26823`。)- 新的 PyErr_SetImportErrorSubclass() 函数允许指定要引发的 ImportError 的子类。 (由 Eric Snow 在 中贡献:问题:`15767`。)
- 新的 PyErr_ResourceWarning() 函数可用于生成 ResourceWarning 提供资源分配的来源。 (由 Victor Stinner 在 中提供:问题:`26567`。)
- 新的 PyOS_FSPath() 函数返回 类路径对象 的文件系统表示。 (由 Brett Cannon 在 中提供:issue:`27186`。)
- PyUnicode_FSConverter() 和 PyUnicode_FSDecoder() 函数现在将接受 类路径对象 。
其他改进
当 --version(简称:-V)被提供两次时,Python 会打印 sys.version 以获取详细信息。
$ ./python -VV Python 3.6.0b4+ (3.6:223967b49e49+, Nov 21 2016, 20:55:04) [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)]
已弃用
新关键字
async
和 await
不建议用作变量、类、函数或模块名称。 由 Python 3.5 中的 PEP 492 引入,它们将成为 Python 3.7 中的正确关键字。 从 Python 3.6 开始,使用 async
或 await
作为名称将生成 DeprecationWarning。
弃用的 Python 行为
在生成器中引发 StopIteration 异常现在将生成 DeprecationWarning,并将在 Python 3.7 中触发 RuntimeError。 有关详细信息,请参阅 PEP 479:更改生成器内部的 StopIteration 处理 。
__aiter__()
方法现在应该直接返回一个异步迭代器,而不是像以前那样返回一个可等待的。 执行前者将触发 DeprecationWarning。 Python 3.7 中将删除向后兼容性。 (由 Yury Selivanov 在 中提供:issue:`27243`。)
不是有效转义序列的反斜杠字符对现在会生成 DeprecationWarning。 尽管这最终会变成 SyntaxError,但这不会适用于多个 Python 版本。 (由 Emanuel Barry 在 中提供:issue:`27364`。)
执行相对导入时,当 __spec__
或 __package__
未定义时,从调用模块退回 __name__
和 __path__
现在会引发 ImportWarning 。 (由 Rose Ames 在 中提供:问题:`25791`。)
弃用的 Python 模块、函数和方法
数据库
与其他 dbm 实现不同,dbm.dumb 模块以 'rw'
模式创建数据库,并允许修改以 'r'
模式打开的数据库。 此行为现已弃用,并将在 3.8 中删除。 (由 Serhiy Storchaka 在 中提供:issue:`21708`。)
分配器
Distribution
构造函数的未记录的 extra_path
参数现在被认为已弃用,如果设置将引发警告。 在未来的 Python 版本中将删除对这个参数的支持。 有关详细信息,请参阅 :issue:`27919`。
导入库
importlib.machinery.SourceFileLoader.load_module() 和 importlib.machinery.SourcelessFileLoader.load_module() 方法现已弃用。 它们是 importlib 中 importlib.abc.Loader.load_module() 的唯一剩余实现,在以前的 Python 版本中没有被弃用,而支持 importlib.abc。 Loader.exec_module()。
importlib.machinery.WindowsRegistryFinder 类现已弃用。 从 3.6.0 开始,它仍然默认添加到 sys.meta_path 中(在 Windows 上),但这在未来版本中可能会发生变化。
操作系统
在 os 函数、compile() 和类似函数中,未公开支持一般 类字节对象 作为路径现在已弃用。 (由 Serhiy Storchaka 在 :issue:`25791` 和 :issue:`26754` 中贡献。)
关于
对正则表达式中间的内联标志 (?letters)
的支持已被弃用,并将在未来的 Python 版本中删除。 正则表达式开头的标志仍然是允许的。 (由 Serhiy Storchaka 在 中提供:issue:`22493`。)
ssl
OpenSSL 0.9.8、1.0.0 和 1.0.1 已弃用且不再受支持。 将来,ssl 模块至少需要 OpenSSL 1.0.2 或 1.1.0。
SSL 相关参数,如 ftplib、http.client、imaplib中的 certfile
、keyfile
和 check_hostname
]、poplib 和 smtplib 已被弃用,取而代之的是 context
。 (由 Christian Heimes 在 中提供:issue:`28022`。)
ssl 模块的一些协议和功能现已弃用。 某些功能在 OpenSSL 的未来版本中将不再可用。 其他功能已被弃用,以支持不同的 API。 (由 Christian Heimes 在 :issue:`28022` 和 :issue:`26470` 中贡献。)
venv
pyvenv
脚本已被弃用,取而代之的是 python3 -m venv
。 这可以防止混淆 Python 解释器 pyvenv
连接到什么以及虚拟环境将使用什么 Python 解释器。 (由 Brett Cannon 在 中提供:issue:`25154`。)
不推荐使用的 C API 函数和类型
未记录的函数 PyUnicode_AsEncodedObject()
、PyUnicode_AsDecodedObject()
、PyUnicode_AsEncodedUnicode()
和 PyUnicode_AsDecodedUnicode()
现已弃用。 请改用基于 通用编解码器的 API 。
弃用的构建选项
--with-system-ffi
配置标志现在在非 macOS UNIX 平台上默认启用。 可以使用 --without-system-ffi
禁用它,但不推荐使用该标志,并且在 Python 3.7 中将不被接受。 macOS 不受此更改的影响。 请注意,许多操作系统分销商在构建他们的系统 Python 时已经使用了 --with-system-ffi
标志。
已移除
API 和功能删除
- 由
'\'
和正则表达式中的 ASCII 字母组成的未知转义现在将导致错误。 在 re.sub() 的替换模板中,它们仍然被允许,但已弃用。 re.LOCALE 标志现在只能用于二进制模式。 inspect.getmoduleinfo()
已删除(自 CPython 3.3 起已弃用)。 inspect.getmodulename() 应该用于获取给定路径的模块名称。 (由 Yury Selivanov 在 :issue:`13248` 中贡献。)traceback.Ignore
类和traceback.usage
、traceback.modname
、traceback.fullmodname
、traceback.find_lines_from_code
、traceback.find_lines
、traceback.find_strings
、traceback.find_executable_lines
方法已从 追溯 模块中删除。 它们是自 Python 3.2 以来已弃用的未记录方法,并且可以从私有方法获得等效功能。- 删除了 tkinter 小部件类中的
tk_menuBar()
和tk_bindForTraversal()
虚拟方法(相应的 Tk 命令自 Tk 4.0 起已过时)。 - zipfile.ZipFile 类的 open() 方法不再支持
'U'
模式(自 Python 3.4 起已弃用)。 使用 io.TextIOWrapper 在 通用换行符 模式下读取压缩文本文件。 - 未记录的
IN
、CDROM
、DLFCN
、TYPES
、CDIO
和STROPTS
模块已被删除。 它们在特定于平台的Lib/plat-*/
目录中可用,但长期过时,跨平台不一致,并且没有维护。 创建这些模块的脚本在 :source:`Tools/scripts/h2py.py` 的源代码分发中仍然可用。 - 已弃用的
asynchat.fifo
类已被删除。
移植到 Python 3.6
本节列出了可能需要更改您的代码的先前描述的更改和其他错误修正。
“python”命令行为的变化
- 带有定义的
COUNT_ALLOCS
、SHOW_ALLOC_COUNT
或SHOW_TRACK_COUNT
宏的特殊 Python 构建的输出现在默认关闭。 可以使用-X showalloccount
选项重新启用它。 它现在输出到stderr
而不是stdout
。 (由 Serhiy Storchaka 在 中提供:issue:`23034`。)
Python API 的变化
open() 将不再允许将
'U'
模式标志与'+'
结合使用。 (由 Jeff Balogh 和 John O'Connor 在 :issue:`2091` 中提供。)sqlite3 不再在 DDL 语句之前隐式提交打开的事务。
在 Linux 上,os.urandom() 现在会阻塞,直到系统 urandom 熵池初始化以提高安全性。
定义 importlib.abc.Loader.exec_module() 时,还必须定义 importlib.abc.Loader.create_module()。
PyErr_SetImportError() 现在在 msg 参数未设置时设置 TypeError。 以前只返回
NULL
。代码对象的
co_lnotab
属性的格式已更改为支持负行号增量。 默认情况下,Python 不会发出带有负行号增量的字节码。 使用frame.f_lineno
、PyFrame_GetLineNumber()
或PyCode_Addr2Line()
的功能不受影响。 直接解码co_lnotab
的函数应更新为对行号增量使用有符号的 8 位整数类型,但这仅用于支持使用负行号增量的应用程序。 请参阅Objects/lnotab_notes.txt
了解co_lnotab
格式及其解码方法,并参阅 PEP 511 了解基本原理。compileall 模块中的函数现在返回布尔值而不是
1
或0
,分别代表成功或失败。 由于布尔值是整数的子类,因此只有在对1
或0
进行身份检查时,这才应该是一个问题。 参见 :issue:`25768`。读取 urllib.parse.urlsplit() 和 urlparse() 结果的
port
属性现在会为超出范围的值引发 ValueError ,而不是返回 None。 参见 :issue:`20059`。imp 模块现在引发 DeprecationWarning 而不是 PendingDeprecationWarning。
以下模块在其
__all__
属性中添加了缺失的 API 以匹配记录的 API:calendar、cgi、csv、 ElementTree, enum, fileinput, ftplib, logging, mailbox[X260types7], [mX260typesX] X281X]、optparse、plistlib、smtpd、子进程、tarfile[X389X]、[X389X]、、和 波 。 这意味着它们将在使用import *
时导出新符号。 (由 Joel Taddei 和 Jacek Kołodziej 在 :issue:`23883` 中提供。)执行相对导入时,如果
__package__
不等于__spec__.parent
,则引发 ImportWarning。 (由 Brett Cannon 在 中提供:问题:`25791`。)当执行相对导入并且不知道父包时,将引发 ImportError。 以前,可以引发 SystemError。 (由 Brett Cannon 在 :issue:`18018` 中贡献。)
基于 socketserver 模块的服务器,包括在 http.server、xmlrpc.server 和 wsgiref.simple_server 中定义的服务器,现在只捕获从 Exception 派生的异常。 因此,如果请求处理程序引发诸如 SystemExit 或 KeyboardInterrupt 之类的异常,则不再调用 handle_error(),并且该异常将停止单线程服务器。 (由 Martin Panter 在 中提供:issue:`23430`。)
spwd.getspnam() 如果用户没有权限,现在会引发 PermissionError 而不是 KeyError。
socket.socket.close() 方法现在在出现错误时引发异常(例如
EBADF
) 是由底层系统调用报告的。 (由 Martin Panter 在 中提供:issue:`26685`。)smtpd.SMTPChannel 和 smtpd.SMTPServer 构造函数的 decode_data 参数现在默认为
False
。 这意味着传递给 process_message() 的参数现在默认是一个字节对象,而process_message()
将被传递关键字参数。 已经按照 3.5 生成的弃用警告更新的代码不会受到影响。dump()、dumps()、load() 和 loads() 函数和 JSONEncoder 的所有可选参数json 模块中的 和 JSONDecoder 类构造函数现在是 仅关键字 。 (由 Serhiy Storchaka 在 :issue:`18726` 中提供。)
不覆盖
type.__new__
的 type 的子类可能不再使用单参数形式来获取对象的类型。作为 PEP 487 的一部分,传递给 type 的关键字参数的处理(元类提示除外,
metaclass
)现在始终委托到 object.__init_subclass__()。 这意味着type.__new__()
和type.__init__()
现在都接受任意关键字参数,但是 object.__init_subclass__()(从type.__new__()
调用)将拒绝它们默认情况下。 接受额外关键字参数的自定义元类需要相应地调整对type.__new__()
的调用(无论是直接调用还是通过 super)。在
distutils.command.sdist.sdist
中,default_format
属性已被移除且不再受尊重。 相反,gzipped tarfile 格式是所有平台上的默认格式,并且没有进行特定于平台的选择。 在发行版构建在 Windows 上并且需要 zip 发行版的环境中,使用包含以下内容的setup.cfg
文件配置项目:[sdist] formats=zip
Setuptools 26.0.0 也将此行为向后移植到早期的 Python 版本。
在 urllib.request 模块和 http.client.HTTPConnection.request() 方法中,如果没有指定 Content-Length 头域并且请求体是文件对象,它现在使用 HTTP 1.1 分块编码发送。 如果必须将文件对象发送到 HTTP 1.0 服务器,则现在必须由调用者指定 Content-Length 值。 (由 Demian Brecht 和 Rolf Krahl 提供,并在 :issue:`12319` 中由 Martin Panter 进行了调整。)
DictReader 现在返回类型为 OrderedDict 的行。 (由 Steve Holden 在 :issue:`27842` 中提供。)
如果平台不支持 crypt.METHOD_CRYPT 将不再添加到
crypt.methods
。 (由 Victor Stinner 在 中提供:问题:`25287`。)namedtuple() 的 verbose 和 rename 参数现在只有关键字。 (由 Raymond Hettinger 在 中提供:issue:`25628`。)
在 Linux 上,ctypes.util.find_library() 现在在
LD_LIBRARY_PATH
中查找共享库。 (由 Vinay Sajip 在 :issue:`9998` 中提供。)imaplib.IMAP4 类现在处理从服务器发送的消息中包含
']'
字符的标志,以提高现实世界的兼容性。 (由 Lita Cho 在 中提供:issue:`21815`。)mmap.write()
函数现在像其他写入方法一样返回写入的字节数。 (由 Jakub Stasiak 在 中提供:issue:`26335`。)pkgutil.iter_modules() 和 pkgutil.walk_packages() 函数现在返回 ModuleInfo 命名元组。 (由 Ramchandra Apte 在 中提供:issue:`17211`。)
re.sub() 现在会针对替换模板中的无效数字组引用引发错误,即使在字符串中找不到该模式。 无效组引用的错误消息现在包括组索引和引用的位置。 (由 SilentGhost、Serhiy Storchaka 在 中提供:issue:`25953`。)
zipfile.ZipFile 现在将为无法识别的压缩值引发 NotImplementedError。 以前提出了一个普通的 RuntimeError。 此外,在关闭的 ZipFile 上调用 ZipFile 方法或在使用
'r'
模式创建的 ZipFile 上调用 write() 方法将引发 ValueError . 以前,在这些场景中会引发 RuntimeError。当自定义元类与零参数 super() 或从方法直接引用到隐式
__class__
闭包变量时,隐式__classcell__
命名空间条目现在必须向上传递到type.__new__
进行初始化。 否则将导致 Python 3.6 中的 DeprecationWarning 和 Python 3.8 中的 RuntimeError。随着 ModuleNotFoundError 的引入,导入系统消费者可能开始期望导入系统替换在适当的时候引发更具体的异常,而不是不太具体的 ImportError。 为了提供与此类消费者的未来兼容性,完全替换 __import__() 的替代导入系统的实现者将需要更新其实现以在根本找不到模块时引发新的子类。 默认导入系统的兼容插件的实现者不需要进行任何更改,因为默认导入系统会在适当的时候引发新的子类。
C API 的变化
- PyMem_Malloc() 分配器系列现在使用 pymalloc 分配器 而不是系统
malloc()
。 调用 PyMem_Malloc() 而不持有 GIL 的应用程序现在可能会崩溃。 将 PYTHONMALLOC 环境变量设置为debug
以验证应用程序中内存分配器的使用情况。 参见 :issue:`26249`。 - Py_Exit()(和主解释器)现在在刷新缓冲数据失败时用 120 覆盖退出状态。 参见 :issue:`5319`。
CPython 字节码更改
Python 3.6 中的 字节码 有几处重大更改。
- Python 解释器现在使用 16 位字码而不是字节码。 (由 Demur Rumed 在 :issue:`26647` 和 :issue:`28050` 中提供了来自 Serhiy Storchaka 和 Victor Stinner 的意见和评论。)
- 新的 :opcode:`FORMAT_VALUE` 和 :opcode:`BUILD_STRING` 操作码作为 格式化字符串文字 实现的一部分。 (由 Eric Smith 在 :issue:`25483` 和 Serhiy Storchaka 在 :issue:`27078` 中贡献。)
- 新的 :opcode:`BUILD_CONST_KEY_MAP` 操作码优化了带有常量键的字典的创建。 (由 Serhiy Storchaka 在 中提供:issue:`27140`。)
- 函数调用操作码已经过大量修改,以获得更好的性能和更简单的实现。 :opcode:`MAKE_FUNCTION`、:opcode:`CALL_FUNCTION`、:opcode:`CALL_FUNCTION_KW` 和 :opcode:`BUILD_CWITH_ X152X] 操作码已修改,添加了新的 :opcode:`CALL_FUNCTION_EX` 和 :opcode:`BUILD_TUPLE_UNPACK_WITH_CALL`,以及 ,[X331X4][X331X4] X318X] 和
MAKE_CLOSURE
操作码已被删除。 (由 :issue:`27095` 中的 Demur Rumed 和 :issue:`27213`、:issue:`28257` 中的 Serhiy Storchaka 贡献。) - 添加了新的 :opcode:`SETUP_ANNOTATIONS` 和 :opcode:`STORE_ANNOTATION` 操作码以支持新的 变量注释 语法。 (由 Ivan Levkivskyi 在 :issue:`27985` 中贡献。)
Python 3.6.2 中的显着变化
新的 make regen-all 构建目标
为了简化交叉编译,并确保在不需要现有 Python 版本可用的情况下可靠地编译 CPython,基于自动工具的构建系统不再尝试根据文件修改时间隐式地重新编译生成的文件。
相反,添加了一个新的 make regen-all
命令以在需要时强制重新生成这些文件(例如 在已经基于预先生成的版本构建了 Python 的初始版本之后)。
还定义了更多选择性的再生目标 - 有关详细信息,请参阅 :source:`Makefile.pre.in`。
(由 Victor Stinner 在 中提供:问题:`23404`。)
版本 3.6.2 中的新功能。
移除 make touch 构建目标
make touch
构建目标以前用于通过更新修改时间请求隐式重新生成生成的文件已被删除。
它已被新的 make regen-all
目标取代。
(由 Victor Stinner 在 中提供:问题:`23404`。)
在 3.6.2 版中更改。
Python 3.6.4 中的显着变化
作为公共 API 一部分的 PyExc_RecursionErrorInst
单例已被删除,因为其成员从未被清除可能会在解释器的最终确定过程中导致段错误。 (由 Xavier de Gaye 在 :issue:`22898` 和 :issue:`30697` 中贡献。)
Python 3.6.5 中的显着变化
locale.localeconv() 函数现在在某些情况下暂时将 LC_CTYPE
语言环境设置为 LC_NUMERIC
语言环境。 (由 Victor Stinner 在 中提供:问题:`31900`。)
Python 3.6.7 中的显着变化
在 3.6.7 中,tokenize 模块现在在提供没有尾随换行符的输入时隐式发出 NEWLINE
标记。 此行为现在与 C 标记器在内部执行的操作相匹配。 (由 Ammar Askar 在 中提供:issue:`33899`。)
Python 3.6.10 中的显着变化
由于重大的安全问题,不再支持 asyncio.loop.create_datagram_endpoint()
的 reuse_address 参数。 这是因为 UDP 中套接字选项 SO_REUSEADDR
的行为。 有关更多详细信息,请参阅 loop.create_datagram_endpoint()
的文档。 (由 Kyle Stanley、Antoine Pitrou 和 Yury Selivanov 在 :issue:`37228` 中提供。)
Python 3.6.13 中的显着变化
早期的 Python 版本允许使用 ;
和 &
作为 urllib.parse.parse_qs() 和 urllib.parse.parse_qsl() 中的查询参数分隔符]。 出于安全考虑,并符合更新的 W3C 建议,这已更改为仅允许单个分隔符键,默认值为 &
。 此更改也会影响 cgi.parse() 和 cgi.parse_multipart(),因为它们在内部使用受影响的函数。 有关更多详细信息,请参阅它们各自的文档。 (由 Adam Goldschmidt、Senthil Kumaran 和 Ken Jin 在 :issue:`42967` 中贡献。)