Python 3.7 的新特性¶
- 编辑:
Elvis Pranskevichus <elvis@magic.io>
本文解释了 Python 3.7 相较于 3.6 的新特性。Python 3.7 于 2018 年 6 月 27 日发布。有关详细信息,请参阅变更日志。
摘要 – 版本亮点¶
新的语法特性
PEP 563,推迟类型注解的求值。
向后不兼容的语法更改
新的库模块
新的内置特性
PEP 553,新的
breakpoint()
函数。
Python 数据模型改进
标准库的重大改进
time
模块获得了对具有纳秒级分辨率的函数的支持。
CPython 实现改进
避免使用 ASCII 作为默认文本编码
PEP 552,确定性的 .pyc
PEP 565,改进的
DeprecationWarning
处理
C API 改进
PEP 539,用于线程局部存储的新 C API
文档改进
此版本在许多方面都有显著的性能改进。优化 部分详细列出了它们。
有关可能影响与以前 Python 版本兼容性的更改列表,请参阅移植到 Python 3.7 部分。
新特性¶
PEP 563: 推迟求值注解¶
Python 中类型提示的出现暴露了PEP 3107 中添加并在 PEP 526 中进一步完善的注解功能存在的两个明显的可用性问题
注解只能使用当前作用域中已有的名称,换句话说,它们不支持任何类型的前向引用;并且
注释源代码会对 Python 程序的启动时间产生不利影响。
通过推迟对注解的求值,可以解决这两个问题。编译器不会在定义时编译执行注解中表达式的代码,而是将注解以字符串形式存储,该字符串形式等效于相关表达式的 AST。如果需要,可以使用 typing.get_type_hints()
在运行时解析注解。在不需要此操作的常见情况下,注解的存储成本更低(因为短字符串会被解释器驻留),并使启动时间更快。
在可用性方面,注解现在支持前向引用,使以下语法有效
class C:
@classmethod
def from_string(cls, source: str) -> C:
...
def validate_b(self, obj: B) -> bool:
...
class B:
...
由于此更改会破坏兼容性,因此需要在 Python 3.7 中使用 __future__
导入在每个模块的基础上启用新行为
from __future__ import annotations
它将在 Python 3.10 中成为默认行为。
另请参阅
- PEP 563 – 推迟对注解的求值
由 Łukasz Langa 编写和实现的 PEP。
PEP 538:传统 C 区域设置强制转换¶
在 Python 3 系列中,一个持续存在的挑战是如何确定一个合理的默认策略,来处理在非 Windows 平台上使用默认 C 或 POSIX 区域设置时,当前隐含的 “7 位 ASCII” 文本编码假设。
PEP 538 更新了默认解释器命令行界面,以自动将该区域设置强制转换为可用的基于 UTF-8 的区域设置,如新的 PYTHONCOERCECLOCALE
环境变量的文档中所述。以这种方式自动设置 LC_CTYPE
意味着核心解释器和了解区域设置的 C 扩展(例如 readline
)都将假设使用 UTF-8 作为默认文本编码,而不是 ASCII。
PEP 11 中的平台支持定义也已更新,以将完整的文本处理支持限制为适当配置的非 ASCII 基于区域设置。
作为此更改的一部分,当使用任何定义的强制转换目标区域设置(当前为 C.UTF-8
、C.utf8
和 UTF-8
)时,stdin
和 stdout
的默认错误处理程序现在是 surrogateescape
(而不是 strict
)。无论区域设置如何,stderr
的默认错误处理程序仍然是 backslashreplace
。
区域设置强制转换默认是静默的,但为了帮助调试可能与区域设置相关的集成问题,可以通过设置 PYTHONCOERCECLOCALE=warn
来请求显式警告(直接在 stderr
上发出)。如果核心解释器初始化时,旧的 C 区域设置仍然处于活动状态,此设置还会导致 Python 运行时发出警告。
虽然 PEP 538 的区域设置强制转换的优点是也会影响扩展模块(例如 GNU readline
),以及子进程(包括运行非 Python 应用程序和旧版本 Python 的进程),但它的缺点是需要正在运行的系统上存在合适的目标区域设置。为了更好地处理没有合适的目标区域设置的情况(例如在 RHEL/CentOS 7 上发生的情况),Python 3.7 还实现了 PEP 540:强制 UTF-8 运行时模式。
另请参阅
- PEP 538 – 将传统的 C 区域设置强制转换为基于 UTF-8 的区域设置
PEP 由 Nick Coghlan 编写和实现。
PEP 540:强制 UTF-8 运行时模式¶
新的 -X
utf8
命令行选项和 PYTHONUTF8
环境变量可用于启用 Python UTF-8 模式。
在 UTF-8 模式下,CPython 会忽略区域设置,并默认使用 UTF-8 编码。sys.stdin
和 sys.stdout
流的错误处理程序设置为 surrogateescape
。
强制 UTF-8 模式可用于更改嵌入式 Python 解释器中的文本处理行为,而无需更改嵌入式应用程序的区域设置。
虽然 PEP 540 的 UTF-8 模式的优点是不管运行系统上可用的区域设置如何,它都能正常工作,但它的缺点是对扩展模块(例如 GNU readline
)、运行非 Python 应用程序的子进程以及运行旧版本 Python 的子进程没有影响。为了减少与此类组件通信时损坏文本数据的风险,Python 3.7 还实现了 PEP 540:强制 UTF-8 运行时模式)。
当区域设置为 C
或 POSIX
,并且 PEP 538 区域设置强制转换功能未能将其更改为基于 UTF-8 的替代项时(无论该失败是由于设置了 PYTHONCOERCECLOCALE=0
,设置了 LC_ALL
,还是缺乏合适的目标区域设置),默认启用 UTF-8 模式。
另请参阅
- PEP 540 – 添加新的 UTF-8 模式
PEP 由 Victor Stinner 编写和实现
PEP 553:内置 breakpoint()
¶
Python 3.7 包括新的内置 breakpoint()
函数,作为进入 Python 调试器的简单且一致的方式。
内置的 breakpoint()
调用 sys.breakpointhook()
。默认情况下,后者导入 pdb
,然后调用 pdb.set_trace()
,但是通过将 sys.breakpointhook()
绑定到您选择的函数,breakpoint()
可以进入任何调试器。此外,可以将环境变量 PYTHONBREAKPOINT
设置为您选择的调试器的可调用对象。设置 PYTHONBREAKPOINT=0
以完全禁用内置的 breakpoint()
。
另请参阅
- PEP 553 – 内置 breakpoint()
PEP 由 Barry Warsaw 编写和实现
PEP 539:线程局部存储的新 C API¶
虽然 Python 为线程局部存储支持提供了 C API;现有的 线程局部存储 (TLS) API 使用 int 来表示所有平台上的 TLS 密钥。这对于官方支持的平台来说通常不是问题,但这既不符合 POSIX 标准,也不具有任何实际意义的可移植性。
PEP 539 通过为 CPython 提供新的 线程特定存储 (TSS) API 来改变这一点,该 API 取代了 CPython 解释器中现有 TLS API 的使用,同时弃用了现有 API。TSS API 使用新的类型 Py_tss_t
而不是 int 来表示 TSS 密钥,这是一种不透明的类型,其定义可能取决于底层的 TLS 实现。因此,这将允许在原生 TLS 密钥的定义方式无法安全地转换为 int 的平台上构建 CPython。
请注意,在原生 TLS 密钥的定义方式无法安全地转换为 int 的平台上,现有 TLS API 的所有函数都将是空操作并立即返回失败。这清楚地表明旧的 API 不支持在无法可靠使用的平台上,并且不会努力添加此类支持。
另请参阅
- PEP 539 – CPython 中用于线程局部存储的新 C-API
PEP 由 Erik M. Bray 编写;由 Masayuki Yamamoto 实现。
PEP 562:模块属性访问的自定义¶
Python 3.7 允许在模块上定义 __getattr__()
,并且当找不到模块属性时会调用它。现在也允许在模块上定义 __dir__()
。
一个典型的应用场景是模块属性的弃用和延迟加载。
另请参阅
- PEP 562 – 模块
__getattr__
和__dir__
由 Ivan Levkivskyi 编写和实现的 PEP
PEP 564:具有纳秒级分辨率的新时间函数¶
现代系统中时钟的分辨率可能超过 time.time()
函数及其变体返回的浮点数的有限精度。为了避免精度损失,PEP 564 向 time
模块添加了六个新的“纳秒”变体的时间函数
新函数将纳秒数作为整数值返回。
测量结果 表明,在 Linux 和 Windows 上,time.time_ns()
的分辨率大约比 time.time()
高 3 倍。
另请参阅
- PEP 564 – 添加具有纳秒分辨率的新时间函数
PEP 由 Victor Stinner 编写和实现
PEP 565:在 __main__
中显示 DeprecationWarning¶
DeprecationWarning
的默认处理方式已更改,以便再次默认显示这些警告,但仅当触发它们的代码直接在 __main__
模块中运行时。因此,单文件脚本的开发者和以交互方式使用 Python 的开发者应该再次开始看到他们使用的 API 的弃用警告,但是由导入的应用程序、库和框架模块触发的弃用警告将继续默认隐藏。
由于此更改,标准库现在允许开发者在三种不同的弃用警告行为之间进行选择
FutureWarning
:默认情况下始终显示,建议用于希望应用程序最终用户看到的警告(例如,针对已弃用的应用程序配置设置)。DeprecationWarning
:默认情况下仅在__main__
中和运行测试时显示,建议用于希望其他 Python 开发者看到的警告,其中版本升级可能会导致行为更改或错误。PendingDeprecationWarning
:默认情况下仅在运行测试时显示,适用于未来版本升级会将警告类别更改为DeprecationWarning
或FutureWarning
的情况。
以前,DeprecationWarning
和 PendingDeprecationWarning
仅在运行测试时可见,这意味着主要编写单文件脚本或以交互方式使用 Python 的开发者可能会对他们使用的 API 中的破坏性更改感到惊讶。
另请参阅
- PEP 565 – 在
__main__
中显示 DeprecationWarning 由 Nick Coghlan 编写和实现的 PEP
PEP 560:对 typing
模块和泛型类型的核心支持¶
最初 PEP 484 的设计方式是不会对核心 CPython 解释器引入任何更改。现在,类型提示和 typing
模块已被社区广泛使用,因此取消了此限制。PEP 引入了两个特殊方法 __class_getitem__()
和 __mro_entries__
,这些方法现在被 typing
中的大多数类和特殊构造所使用。因此,类型相关的各种操作速度提高了 7 倍,泛型类型可以在没有元类冲突的情况下使用,并且修复了 typing
模块中的几个长期存在的错误。
另请参阅
- PEP 560 – 对 typing 模块和泛型类型的核心支持
由 Ivan Levkivskyi 编写和实现的 PEP
PEP 552:基于哈希的 .pyc 文件¶
Python 传统上通过将源代码元数据(最后修改的时间戳和大小)与生成时保存在缓存文件头中的源代码元数据进行比较来检查字节码缓存文件(即 .pyc
文件)的最新程度。虽然有效,但这种失效方法有其缺点。当文件系统时间戳太粗糙时,Python 可能会错过源代码更新,从而导致用户困惑。此外,在缓存文件中包含时间戳对于构建可重现性和基于内容的构建系统来说是有问题的。
PEP 552 扩展了 pyc 格式,允许使用源文件的哈希值而不是源时间戳来执行失效。这种 .pyc
文件称为“基于哈希的”。默认情况下,Python 仍然使用基于时间戳的失效,并且不会在运行时生成基于哈希的 .pyc
文件。基于哈希的 .pyc
文件可以使用 py_compile
或 compileall
生成。
基于哈希的 .pyc
文件有两种变体:已检查的和未检查的。Python 在运行时会根据相应的源文件验证已检查的基于哈希的 .pyc
文件,但不会对未检查的基于哈希的 pyc 文件执行此操作。对于 Python 外部的系统(例如,构建系统)负责保持 .pyc
文件最新的环境,未检查的基于哈希的 .pyc
文件是一种有用的性能优化。
有关更多信息,请参见 缓存字节码失效。
另请参阅
- PEP 552 – 确定性的 pyc
由 Benjamin Peterson 编写和实现的 PEP
PEP 545:Python 文档翻译¶
PEP 545 描述了创建和维护 Python 文档翻译的过程。
已添加三个新的翻译版本
另请参阅
- PEP 545 – Python 文档翻译
由 Julien Palard、Inada Naoki 和 Victor Stinner 编写和实现的 PEP。
Python 开发模式 (-X dev)¶
新的 -X
dev
命令行选项或新的 PYTHONDEVMODE
环境变量可用于启用 Python 开发模式。在开发模式下,Python 执行默认情况下启用过于昂贵的额外运行时检查。有关完整说明,请参见 Python 开发模式 文档。
其他语言变更¶
由于实现上的问题,在
await
表达式和包含async for
子句的推导式在格式化字符串字面值中的表达式中是非法的。在 Python 3.7 中,此限制被取消。现在可以向函数传递超过 255 个参数,并且函数现在可以拥有超过 255 个参数。(由 Serhiy Storchaka 在 bpo-12844 和 bpo-18896 中贡献。)
bytes.fromhex()
和bytearray.fromhex()
现在忽略所有 ASCII 空白字符,而不仅仅是空格。(由 Robert Xiao 在 bpo-28927 中贡献。)str
、bytes
和bytearray
新增了对新的isascii()
方法的支持,该方法可用于测试字符串或字节是否仅包含 ASCII 字符。(由 INADA Naoki 在 bpo-32677 中贡献。)当
from ... import ...
失败时,ImportError
现在会显示模块名称和模块的__file__
路径。(由 Matthias Bussonnier 在 bpo-29546 中贡献。)现在支持涉及将子模块绑定到名称的绝对导入的循环导入。(由 Serhiy Storchaka 在 bpo-30024 中贡献。)
object.__format__(x, '')
现在等效于str(x)
而不是format(str(self), '')
。(由 Serhiy Storchaka 在 bpo-28974 中贡献。)为了更好地支持动态创建堆栈跟踪,现在可以从 Python 代码实例化
types.TracebackType
,并且tb_next
属性现在是可写的。(由 Nathaniel J. Smith 在 bpo-30579 中贡献。)当使用
-m
开关时,sys.path[0]
现在会被立即扩展到完整的起始目录路径,而不是保留为空目录(这允许在发生导入时从*当前*工作目录进行导入)(由 Nick Coghlan 在 bpo-33053 中贡献。)新的
-X
importtime
选项或PYTHONPROFILEIMPORTTIME
环境变量可用于显示每个模块导入的计时。(由 Inada Naoki 在 bpo-31415 中贡献。)
新模块¶
contextvars¶
新的 contextvars
模块和一组 新的 C API 引入了对*上下文变量*的支持。上下文变量在概念上类似于线程局部变量。与 TLS 不同,上下文变量可以正确地支持异步代码。
asyncio
和 decimal
模块已更新,可以开箱即用地使用和支持上下文变量。特别是,活动的十进制上下文现在存储在上下文变量中,这使得十进制运算可以在异步代码中使用正确的上下文。
另请参阅
- PEP 567 – 上下文变量
由 Yury Selivanov 编写和实现的 PEP
dataclasses¶
新的 dataclass()
装饰器提供了一种声明*数据类*的方法。数据类使用类变量注解描述其属性。其构造函数和其他魔术方法(如 __repr__()
、__eq__()
和 __hash__()
)会自动生成。
示例
@dataclass
class Point:
x: float
y: float
z: float = 0.0
p = Point(1.5, 2.5)
print(p) # produces "Point(x=1.5, y=2.5, z=0.0)"
另请参阅
- PEP 557 – 数据类
由 Eric V. Smith 编写和实现的 PEP
importlib.resources¶
新的 importlib.resources
模块提供了几个新的 API 和一个新的 ABC,用于访问、打开和读取包内的*资源*。资源大致类似于包内的文件,但它们不必是物理文件系统上的实际文件。模块加载器可以提供一个 get_resource_reader()
函数,该函数返回一个 importlib.abc.ResourceReader
实例来支持这个新的 API。内置的文件路径加载器和 zip 文件加载器都支持此功能。
由 Barry Warsaw 和 Brett Cannon 在 bpo-32248 中贡献。
另请参阅
importlib_resources – 适用于早期 Python 版本的 PyPI 向后移植。
改进的模块¶
argparse¶
新的 ArgumentParser.parse_intermixed_args()
方法允许混合使用选项和位置参数。(由 paul.j3 在 bpo-14191 中贡献。)
asyncio¶
asyncio
模块收到了许多新功能、可用性以及 性能改进。值得注意的变化包括
新的 临时
asyncio.run()
函数可以用于通过自动创建和销毁事件循环来从同步代码运行协程。(由 Yury Selivanov 在 bpo-32314 中贡献。)asyncio 获得了对
contextvars
的支持。loop.call_soon()
、loop.call_soon_threadsafe()
、loop.call_later()
、loop.call_at()
和Future.add_done_callback()
有一个新的可选的仅限关键字的 *context* 参数。Tasks
现在会自动跟踪它们的上下文。有关更多详细信息,请参阅 PEP 567。(由 Yury Selivanov 在 bpo-32436 中贡献。)新增了
asyncio.create_task()
函数,作为asyncio.get_event_loop().create_task()
的快捷方式。(由 Andrew Svetlov 在 bpo-32311 中贡献。)新的
loop.start_tls()
方法可用于将现有连接升级为 TLS。(由 Yury Selivanov 在 bpo-23749 中贡献。)新的
loop.sock_recv_into()
方法允许直接将数据从套接字读取到提供的缓冲区中,从而减少数据复制。(由 Antoine Pitrou 在 bpo-31819 中贡献。)新的
asyncio.current_task()
函数返回当前正在运行的Task
实例,新的asyncio.all_tasks()
函数返回给定循环中所有现有的Task
实例的集合。Task.current_task()
和Task.all_tasks()
方法已被弃用。(由 Andrew Svetlov 在 bpo-32250 中贡献。)新的 *临时*
BufferedProtocol
类允许实现对接收缓冲区进行手动控制的流协议。(由 Yury Selivanov 在 bpo-32251 中贡献。)新的
asyncio.get_running_loop()
函数返回当前正在运行的循环,如果没有正在运行的循环,则引发RuntimeError
异常。 这与asyncio.get_event_loop()
不同,后者在没有运行的事件循环时会 *创建* 一个新的事件循环。(由 Yury Selivanov 在 bpo-32269 中贡献。)新的
StreamWriter.wait_closed()
协程方法允许等待直到流写入器关闭。 新的StreamWriter.is_closing()
方法可用于确定写入器是否正在关闭。(由 Andrew Svetlov 在 bpo-32391 中贡献。)新的
loop.sock_sendfile()
协程方法允许在可能的情况下使用os.sendfile
发送文件。(由 Andrew Svetlov 在 bpo-32410 中贡献。)新的
Future.get_loop()
和Task.get_loop()
方法返回创建任务或 future 的循环实例。Server.get_loop()
允许对asyncio.Server
对象执行相同的操作。(由 Yury Selivanov 在 bpo-32415 中贡献,Srinivas Reddy Thatiparthy 在 bpo-32418 中贡献。)现在可以控制
asyncio.Server
实例开始服务的方式。 以前,服务器会在创建时立即开始服务。loop.create_server()
和loop.create_unix_server()
的新 *start_serving* 关键字参数,以及Server.start_serving()
和Server.serve_forever()
可用于解耦服务器实例化和服务。 如果服务器正在服务,则新的Server.is_serving()
方法返回True
。Server
对象现在是异步上下文管理器srv = await loop.create_server(...) async with srv: # some code # At this point, srv is closed and no longer accepts new connections.
(由 Yury Selivanov 在 bpo-32662 中贡献。)
由
loop.call_later()
返回的回调对象获得了新的when()
方法,该方法返回绝对计划的回调时间戳。(由 Andrew Svetlov 在 bpo-32741 中贡献。)loop.create_datagram_endpoint()
方法增加了对 Unix 套接字的支持。(由 Quentin Dawans 在 bpo-31245 中贡献。)asyncio.open_connection()
、asyncio.start_server()
函数、loop.create_connection()
、loop.create_server()
、loop.create_accepted_socket()
方法及其相应的 UNIX 套接字变体现在接受 *ssl_handshake_timeout* 关键字参数。(由 Neil Aspinall 在 bpo-29970 中贡献。)如果回调已被取消,则新的
Handle.cancelled()
方法返回True
。(由 Marat Sharafutdinov 在 bpo-31943 中贡献。)asyncio 源代码已转换为使用
async
/await
语法。(由 Andrew Svetlov 在 bpo-32193 中贡献。)新的
ReadTransport.is_reading()
方法可用于确定传输的读取状态。 此外,对ReadTransport.resume_reading()
和ReadTransport.pause_reading()
的调用现在是幂等的。(由 Yury Selivanov 在 bpo-32356 中贡献。)在
asyncio
中,Linux 上的 TCP 套接字现在默认使用TCP_NODELAY
标志创建。(由 Yury Selivanov 和 Victor Stinner 在bpo-27456中贡献。)已取消任务中发生的异常不再被记录。(由 Yury Selivanov 在bpo-30508中贡献。)
新的
WindowsSelectorEventLoopPolicy
和WindowsProactorEventLoopPolicy
类。(由 Yury Selivanov 在 bpo-33792中贡献。)
几个 asyncio
API 已弃用。
binascii¶
b2a_uu()
函数现在接受一个可选的 *backtick* 关键字参数。当它为 true 时,零将用 '`'
而不是空格表示。(由 Xiang Zhang 在 bpo-30103 中贡献。)
calendar¶
HTMLCalendar
类具有新的类属性,可简化生成的 HTML 日历中 CSS 类的自定义。(由 Oz Tiram 在 bpo-30095 中贡献。)
collections¶
collections.namedtuple()
现在支持默认值。(由 Raymond Hettinger 在 bpo-32320 中贡献。)
compileall¶
compileall.compile_dir()
学习了新的 *invalidation_mode* 参数,可用于启用基于哈希的 .pyc 失效。失效模式也可以使用新的 --invalidation-mode
参数在命令行中指定。(由 Benjamin Peterson 在bpo-31650 中贡献。)
concurrent.futures¶
ProcessPoolExecutor
和 ThreadPoolExecutor
现在支持新的 *initializer* 和 *initargs* 构造函数参数。(由 Antoine Pitrou 在 bpo-21423 中贡献。)
ProcessPoolExecutor
现在可以通过新的 *mp_context* 参数获取多进程上下文。(由 Thomas Moreau 在 bpo-31540 中贡献。)
contextlib¶
新的 nullcontext()
是比 ExitStack
更简单、更快的空操作上下文管理器。(由 Jesse-Bakker 在 bpo-10049 中贡献。)
新的 asynccontextmanager()
、AbstractAsyncContextManager
和 AsyncExitStack
已被添加以补充其同步对应项。(由 Jelle Zijlstra 在 bpo-29679 和 bpo-30241 中贡献,由 Alexander Mohr 和 Ilya Kulakov 在 bpo-29302 中贡献。)
cProfile¶
cProfile
命令行现在接受 -m module_name
作为脚本路径的替代方法。(由 Sanyam Khurana 在bpo-21862中贡献。)
crypt¶
crypt
模块现在支持 Blowfish 哈希方法。(由 Serhiy Storchaka 在 bpo-31664 中贡献。)
mksalt()
函数现在允许指定哈希的轮数。(由 Serhiy Storchaka 在 bpo-31702 中贡献。)
datetime¶
新的 datetime.fromisoformat()
方法从 datetime.isoformat()
输出的格式之一的字符串构造一个 datetime
对象。(由 Paul Ganssle 在 bpo-15873 中贡献。)
dbm¶
dbm.dumb
现在支持读取只读文件,并且在未更改索引文件时不写入索引文件。
decimal¶
decimal
模块现在使用 上下文变量 来存储十进制上下文。(由 Yury Selivanov 在 bpo-32630 中贡献。)
dis¶
dis()
函数现在能够反汇编嵌套的代码对象(推导式、生成器表达式和嵌套函数的代码,以及用于构建嵌套类的代码)。反汇编递归的最大深度由新的 *depth* 参数控制。(由 Serhiy Storchaka 在 bpo-11822 中贡献。)
distutils¶
README.rst
现在包含在 distutils 标准 README 列表中,因此包含在源代码发行版中。(由 Ryan Gonzalez 在 bpo-11913 中贡献。)
enum¶
Enum
学习了新的 _ignore_
类属性,允许列出不应成为枚举成员的属性的名称。(由 Ethan Furman 在 bpo-31801 中贡献。)
在 Python 3.8 中,尝试检查 Enum
类中的非枚举对象会引发 TypeError
(例如 1 in Color
);类似地,尝试检查 Flag
成员中的非 Flag 对象会引发 TypeError
(例如 1 in Perm.RW
);目前,这两个操作都返回 False
,并且已被弃用。(由 Ethan Furman 在 bpo-33217 中贡献。)
functools¶
functools.singledispatch()
现在支持使用类型注解注册实现。(由 Łukasz Langa 在bpo-32227中贡献。)
gc¶
新的 gc.freeze()
函数允许冻结垃圾收集器跟踪的所有对象,并将它们排除在未来的集合之外。这可以在 POSIX fork()
调用之前使用,以使 GC 对写入时复制友好或加速收集。新的 gc.unfreeze()
函数会反转此操作。此外,gc.get_freeze_count()
可用于获取冻结对象的数量。(由 Li Zekun 在bpo-31558 中贡献。)
hmac¶
现在,hmac
模块有了一个优化的单次 digest()
函数,它的速度比 HMAC()
快三倍。(由 Christian Heimes 在 bpo-32433 中贡献。)
http.client¶
HTTPConnection
和 HTTPSConnection
现在支持新的 blocksize 参数,以提高上传吞吐量。(由 Nir Soffer 在 bpo-31945 中贡献。)
http.server¶
SimpleHTTPRequestHandler
现在支持 HTTP If-Modified-Since
标头。如果目标文件在标头中指定的时间之后未被修改,服务器将返回 304 响应状态。(由 Pierre Quentel 在 bpo-29654 中贡献。)
SimpleHTTPRequestHandler
接受新的 directory 参数,以及新的 --directory
命令行参数。使用此参数,服务器将服务于指定的目录,默认情况下它使用当前工作目录。(由 Stéphane Wirtel 和 Julien Palard 在 bpo-28707 中贡献。)
新的 ThreadingHTTPServer
类使用线程通过 ThreadingMixin
处理请求。当使用 -m
运行 http.server
时使用它。(由 Julien Palard 在 bpo-31639 中贡献。)
idlelib 和 IDLE¶
自动完成的多个修复。(由 Louie Lu 在 bpo-15786 中贡献。)
模块浏览器(在文件菜单上,以前称为类浏览器)现在除了顶层函数和类之外,还显示嵌套的函数和类。(由 Guilherme Polo,Cheryl Sabella 和 Terry Jan Reedy 在 bpo-1612262 中贡献。)
“设置”对话框(“选项”,“配置 IDLE”)已部分重写,以改进外观和功能。(由 Cheryl Sabella 和 Terry Jan Reedy 在多个问题中贡献。)
字体示例现在包含非拉丁字符的选择,以便用户可以更好地了解选择特定字体的影响。(由 Terry Jan Reedy 在 bpo-13802 中贡献。)可以编辑示例以包含其他字符。(由 Serhiy Storchaka 在 bpo-31860 中贡献。)
以前作为扩展实现的 IDLE 功能已重新实现为正常功能。它们的设置已从“扩展”选项卡移动到其他对话框选项卡。(由 Charles Wohlganger 和 Terry Jan Reedy 在 bpo-27099 中贡献。)
修订编辑器代码上下文选项。框显示最多 maxlines 的所有上下文行。单击上下文行会将编辑器跳转到该行。自定义主题的上下文颜色已添加到“设置”对话框的“高亮显示”选项卡。(由 Cheryl Sabella 和 Terry Jan Reedy 在 bpo-33642,bpo-33768 和 bpo-33679 中贡献。)
在 Windows 上,新的 API 调用会告诉 Windows tk 为 DPI 缩放。在 Windows 8.1+ 或 10 上,Python 二进制文件的 DPI 兼容性属性保持不变,并且显示器分辨率大于 96 DPI,这应该使文本和线条更清晰。否则应该没有效果。(由 Terry Jan Reedy 在 bpo-33656 中贡献。)
3.7.1 中的新功能
超过 N 行(默认为 50 行)的输出被压缩成一个按钮。可以在“设置”对话框的“常规”页面的“PyShell”部分中更改 N。可以通过右键单击输出来压缩更少但可能更长的行。可以通过双击按钮将压缩的输出就地展开,或者通过右键单击按钮将其展开到剪贴板或单独的窗口中。(由 Tal Einat 在 bpo-1529353 中贡献。)
以上更改已向后移植到 3.6 维护版本。
3.7.4 中的新功能
将“运行自定义”添加到“运行”菜单,以使用自定义设置运行模块。输入的任何命令行参数都将添加到 sys.argv。它们会在下一次自定义运行时重新出现在框中。还可以禁止正常的 Shell 主模块重新启动。(由 Cheryl Sabella,Terry Jan Reedy 和其他人在 bpo-5680 和 bpo-37627 中贡献。)
3.7.5 中的新功能
为 IDLE 编辑器窗口添加可选的行号。除非在配置对话框的“常规”选项卡中另行设置,否则打开的窗口不显示行号。现有窗口的行号在“选项”菜单中显示和隐藏。(由 Tal Einat 和 Saimadhav Heblikar 在 bpo-17535 中贡献。)
importlib¶
引入了 importlib.abc.ResourceReader
ABC,以支持从包中加载资源。另请参见 importlib.resources。(由 Barry Warsaw,Brett Cannon 在 bpo-32248 中贡献。)
如果模块缺少 spec,importlib.reload()
现在会引发 ModuleNotFoundError
。(由 Garvit Khatri 在 bpo-29851 中贡献。)
如果指定的父模块不是包(即缺少 __path__
属性),importlib.find_spec()
现在会引发 ModuleNotFoundError
,而不是 AttributeError
。(由 Milan Oberkirch 在 bpo-30436 中贡献。)
新的 importlib.source_hash()
可用于计算传递的源的哈希值。一个 基于哈希的 .pyc 文件 嵌入了此函数返回的值。
io¶
新的 TextIOWrapper.reconfigure()
方法可用于使用新设置重新配置文本流。(由 Antoine Pitrou 在 bpo-30526 和 INADA Naoki 在 bpo-15216 中贡献。)
ipaddress¶
新的 subnet_of()
和 supernet_of()
方法 ipaddress.IPv6Network
和 ipaddress.IPv4Network
可用于网络包含测试。(由 Michel Albert 和 Cheryl Sabella 在 bpo-20825 中贡献。)
itertools¶
itertools.islice()
现在接受 类整数对象
作为 start、stop 和 slice 参数。(由 Will Roberts 在 bpo-30537 中贡献。)
locale¶
locale.format_string()
的新 monetary 参数可用于使转换使用货币千位分隔符和分组字符串。(由 Garvit 在 bpo-10379 中贡献。)
现在,在 Android 上或在强制 UTF-8 模式下,locale.getpreferredencoding()
函数总是返回 'UTF-8'
。
日志记录¶
现在可以 pickle Logger
实例。(由 Vinay Sajip 在 bpo-30520 中贡献。)
新的 StreamHandler.setStream()
方法可用于在处理程序创建后替换日志记录器流。(由 Vinay Sajip 在 bpo-30522 中贡献。)
现在可以在传递给 logging.config.fileConfig()
的配置中,为处理程序构造函数指定关键字参数。(由 Preston Landers 在 bpo-31080 中贡献。)
数学¶
新的 math.remainder()
函数实现了 IEEE 754 风格的余数运算。(由 Mark Dickinson 在 bpo-29962 中贡献。)
mimetypes¶
.bmp 的 MIME 类型已从 'image/x-ms-bmp'
更改为 'image/bmp'
。(由 Nitish Chandra 在 bpo-22589 中贡献。)
msilib¶
新的 Database.Close()
方法可用于关闭 MSI 数据库。(由 Berker Peksag 在 bpo-20486 中贡献。)
多进程¶
新的 Process.close()
方法显式地关闭进程对象并释放与之关联的所有资源。如果底层进程仍在运行,则会引发 ValueError
。(由 Antoine Pitrou 在 bpo-30596 中贡献。)
新的 Process.kill()
方法可用于使用 Unix 上的 SIGKILL
信号终止进程。(由 Vitor Pereira 在 bpo-30794 中贡献。)
由 Process
创建的非守护线程现在在进程退出时被加入。(由 Antoine Pitrou 在 bpo-18966 中贡献。)
os¶
现在,os.fwalk()
接受 path 参数作为 bytes
。(由 Serhiy Storchaka 在 bpo-28682 中贡献。)
os.scandir()
获得了对文件描述符 的支持。(由 Serhiy Storchaka 在 bpo-25996 中贡献。)
新的 register_at_fork()
函数允许注册在进程 fork 时执行的 Python 回调。(由 Antoine Pitrou 在 bpo-16500 中贡献。)
添加了 os.preadv()
(合并了 os.readv()
和 os.pread()
的功能) 和 os.pwritev()
函数 (合并了 os.writev()
和 os.pwrite()
的功能)。(由 Pablo Galindo 在 bpo-31368 中贡献。)
os.makedirs()
的 mode 参数不再影响新创建的中间级别目录的文件权限位。(由 Serhiy Storchaka 在 bpo-19930 中贡献。)
现在,os.dup2()
返回新的文件描述符。以前,总是返回 None
。(由 Benjamin Peterson 在 bpo-32441 中贡献。)
现在,由 os.stat()
返回的结构在 Solaris 及其衍生版本上包含 st_fstype
属性。(由 Jesús Cea Avión 在 bpo-32659 中贡献。)
pathlib¶
新的 Path.is_mount()
方法现在在 POSIX 系统上可用,可用于确定路径是否为挂载点。(由 Cooper Ry Lees 在 bpo-30897 中贡献。)
pdb¶
现在,pdb.set_trace()
接受可选的仅限关键字的 header 参数。如果给定,它将在调试开始之前打印到控制台。(由 Barry Warsaw 在 bpo-31389 中贡献。)
pdb
命令行现在接受 -m module_name
作为脚本文件的替代方法。(由 Mario Corchero 在 bpo-32206 中贡献。)
py_compile¶
py_compile.compile()
– 以及扩展的 compileall
– 现在通过无条件地为基于哈希的验证创建 .pyc
文件来遵循 SOURCE_DATE_EPOCH
环境变量。这允许在急切创建 .pyc
文件时保证其可重现构建。(由 Bernhard M. Wiedemann 在 bpo-29708 中贡献。)
pydoc¶
现在,pydoc 服务器可以绑定到由新的 -n
命令行参数指定的任意主机名。(由 Feanil Patel 在 bpo-31128 中贡献。)
queue¶
新的 SimpleQueue
类是一个无界的 FIFO 队列。(由 Antoine Pitrou 在 bpo-14976 中贡献。)
re¶
标志 re.ASCII
、re.LOCALE
和 re.UNICODE
可以在组的范围内设置。(由 Serhiy Storchaka 在 bpo-31690 中贡献。)
现在,re.split()
支持拆分像 r'\b'
、'^$'
或 (?=-)
这样与空字符串匹配的模式。(由 Serhiy Storchaka 在 bpo-25054 中贡献。)
使用 re.LOCALE
标志编译的正则表达式不再依赖于编译时的区域设置。区域设置仅在编译后的正则表达式使用时应用。(由 Serhiy Storchaka 在 bpo-30215 中贡献。)
如果正则表达式包含将来语义会发生更改的字符集结构,例如嵌套集合和集合运算,则现在会发出 FutureWarning
。(由 Serhiy Storchaka 在 bpo-30349 中贡献。)
编译后的正则表达式和匹配对象现在可以使用 copy.copy()
和 copy.deepcopy()
进行复制。(由 Serhiy Storchaka 在 bpo-10076 中贡献。)
signal¶
signal.set_wakeup_fd()
函数新增的 *warn_on_full_buffer* 参数,使得可以指定当唤醒缓冲区溢出时,Python 是否在 stderr 上打印警告。(由 Nathaniel J. Smith 在 bpo-30050 中贡献。)
socket¶
新的 socket.getblocking()
方法,如果套接字处于阻塞模式则返回 True
,否则返回 False
。(由 Yury Selivanov 在 bpo-32373 中贡献。)
新的 socket.close()
函数关闭传递的套接字文件描述符。为了在不同平台之间获得更好的兼容性,应该使用此函数而不是 os.close()
。(由 Christian Heimes 在 bpo-32454 中贡献。)
socket
模块现在公开了 socket.TCP_CONGESTION
(Linux 2.6.13), socket.TCP_USER_TIMEOUT
(Linux 2.6.37), 和 socket.TCP_NOTSENT_LOWAT
(Linux 3.12) 常量。(由 Omar Sandoval 在 bpo-26273 中贡献,以及 Nathaniel J. Smith 在 bpo-29728 中贡献。)
已添加对 socket.AF_VSOCK
套接字的支持,以允许虚拟机及其主机之间进行通信。(由 Cathy Avery 在 bpo-27584 中贡献。)
套接字现在默认从文件描述符自动检测系列、类型和协议。(由 Christian Heimes 在 bpo-28134 中贡献。)
socketserver¶
socketserver.ThreadingMixIn.server_close()
现在等待所有非守护线程完成。socketserver.ForkingMixIn.server_close()
现在等待所有子进程完成。
向 socketserver.ForkingMixIn
和 socketserver.ThreadingMixIn
类添加了一个新的 socketserver.ForkingMixIn.block_on_close
类属性。将该类属性设置为 False
可获得 3.7 之前的行为。
sqlite3¶
当底层 SQLite 库的版本为 3.6.11 或更高时,sqlite3.Connection
现在公开 backup()
方法。(由 Lele Gaifax 在 bpo-27645 中贡献。)
sqlite3.connect()
的 *database* 参数现在接受任何 路径类对象,而不仅仅是字符串。(由 Anders Lorentsen 在 bpo-31843 中贡献。)
ssl¶
ssl
模块现在使用 OpenSSL 的内置 API 而不是 match_hostname()
来检查主机名或 IP 地址。值在 TLS 握手期间进行验证。任何证书验证错误,包括主机名检查失败,现在都会引发 SSLCertVerificationError
并中止握手,并带有正确的 TLS 警报消息。新的异常包含附加信息。可以使用 SSLContext.hostname_checks_common_name
自定义主机名验证。(由 Christian Heimes 在 bpo-31399 中贡献。)
注意
改进的主机名检查需要与 OpenSSL 1.0.2 或 1.1 兼容的 *libssl* 实现。因此,不再支持 OpenSSL 0.9.8 和 1.0.1(有关更多详细信息,请参阅 平台支持移除)。ssl 模块主要与 LibreSSL 2.7.2 及更新版本兼容。
ssl
模块不再在 SNI TLS 扩展中发送 IP 地址。(由 Christian Heimes 在 bpo-32185 中贡献。)
match_hostname()
不再支持部分通配符,例如 www*.example.org
。(由 Mandeep Singh 在 bpo-23033 中贡献,以及 Christian Heimes 在 bpo-31399 中贡献。)
ssl
模块的默认密码套件选择现在使用黑名单方法,而不是硬编码的白名单。Python 不再重新启用已被 OpenSSL 安全更新阻止的密码。默认密码套件选择可以在编译时配置。(由 Christian Heimes 在 bpo-31429 中贡献。)
现在支持验证包含国际化域名 (IDN) 的服务器证书。作为此更改的一部分,SSLSocket.server_hostname
属性现在以 A 标签形式 ("xn--pythn-mua.org"
) 存储预期的主机名,而不是以 U 标签形式 ("pythön.org"
)。(由 Nathaniel J. Smith 和 Christian Heimes 在 bpo-28414 中贡献。)
ssl
模块初步和实验性地支持 TLS 1.3 和 OpenSSL 1.1.1。在 Python 3.7.0 发布时,OpenSSL 1.1.1 仍在开发中,TLS 1.3 尚未最终确定。TLS 1.3 握手和协议的行为与 TLS 1.2 及更早版本略有不同,请参阅 TLS 1.3。(由 Christian Heimes 在 bpo-32947, bpo-20995, bpo-29136, bpo-30622 和 bpo-33618 中贡献)
SSLSocket
和 SSLObject
不再有公共构造函数。直接实例化从来都不是一个文档化和支持的功能。实例必须使用 SSLContext
方法 wrap_socket()
和 wrap_bio()
创建。(由 Christian Heimes 在 bpo-32951 中贡献)
OpenSSL 1.1 的 API 提供了设置最小和最大 TLS 协议版本的功能,可通过 SSLContext.minimum_version
和 SSLContext.maximum_version
访问。支持的协议由几个新的标志指示,例如 HAS_TLSv1_1
。(由 Christian Heimes 在 bpo-32609 中贡献。)
添加了 ssl.SSLContext.post_handshake_auth
来启用,以及 ssl.SSLSocket.verify_client_post_handshake()
来启动 TLS 1.3 后握手身份验证。(由 Christian Heimes 在 gh-78851 中贡献。)
字符串¶
string.Template
现在允许你分别修改带花括号占位符和不带花括号占位符的正则表达式模式。(由 Barry Warsaw 在 bpo-1198569 中贡献。)
subprocess¶
subprocess.run()
函数接受新的 *capture_output* 关键字参数。当为 true 时,将捕获 stdout 和 stderr。这等效于将 subprocess.PIPE
作为 *stdout* 和 *stderr* 参数传递。(由 Bo Bayles 在 bpo-32102 中贡献。)
subprocess.run
函数和 subprocess.Popen
构造函数现在接受 *text* 关键字参数作为 *universal_newlines* 的别名。(由 Andrew Clegg 在 bpo-31756 中贡献。)
在 Windows 上,当重定向标准句柄时,*close_fds* 的默认值从 False
更改为 True
。现在可以在重定向标准句柄时将 *close_fds* 设置为 true。请参阅 subprocess.Popen
。这意味着 *close_fds* 现在在所有支持的平台上默认为 True
。(由 Segev Finer 在 bpo-19764 中贡献。)
subprocess 模块现在在 subprocess.call()
、subprocess.run()
或在 Popen
上下文管理器中处理 KeyboardInterrupt
时更加优雅。现在,它会等待子进程退出一小段时间,然后再继续处理 KeyboardInterrupt
异常。(由 Gregory P. Smith 在 bpo-25942 中贡献。)
sys¶
新的 sys.breakpointhook()
钩子函数由内置的 breakpoint()
调用。(由 Barry Warsaw 在 bpo-31353 中贡献。)
在 Android 上,新的 sys.getandroidapilevel()
返回构建时的 Android API 版本。(由 Victor Stinner 在 bpo-28740 中贡献。)
新的 sys.get_coroutine_origin_tracking_depth()
函数返回当前协程源跟踪深度,该深度由新的 sys.set_coroutine_origin_tracking_depth()
设置。asyncio
已转换为使用此新 API,而不是已弃用的 sys.set_coroutine_wrapper()
。(由 Nathaniel J. Smith 在 bpo-32591 中贡献。)
time¶
PEP 564 向 time
模块添加了六个具有纳秒分辨率的新函数
添加了新的时钟标识符
time.CLOCK_BOOTTIME
(Linux):与time.CLOCK_MONOTONIC
相同,但它还包括系统暂停的任何时间。time.CLOCK_PROF
(FreeBSD、NetBSD 和 OpenBSD):高分辨率的按进程 CPU 计时器。time.CLOCK_UPTIME
(FreeBSD、OpenBSD):绝对值是系统运行且未暂停的时间,提供准确的正常运行时间测量的时钟。
新的 time.thread_time()
和 time.thread_time_ns()
函数可用于获取每个线程的 CPU 时间测量值。(由 Antoine Pitrou 在 bpo-32025 中贡献。)
新的 time.pthread_getcpuclockid()
函数返回线程特定的 CPU 时间时钟的时钟 ID。
tkinter¶
现在可以使用新的 tkinter.ttk.Spinbox
类。(由 Alan Moore 在 bpo-32585 中贡献。)
tracemalloc¶
tracemalloc.Traceback
的行为更像常规的回溯,按从最旧到最近的顺序对帧进行排序。Traceback.format()
现在接受负数 *limit*,将结果截断为 abs(limit)
最旧的帧。要获得旧的行为,请使用 Traceback.format()
的新 *most_recent_first* 参数。(由 Jesse Bakker 在 bpo-32121 中贡献。)
types¶
现在可以使用新的 WrapperDescriptorType
、MethodWrapperType
、MethodDescriptorType
和 ClassMethodDescriptorType
类。(由 Manuel Krebber 和 Guido van Rossum 在 bpo-29377 中贡献,以及 Serhiy Storchaka 在 bpo-32265 中贡献。)
新的 types.resolve_bases()
函数按照 PEP 560 的规定动态解析 MRO 条目。(由 Ivan Levkivskyi 在 bpo-32717 中贡献。)
unicodedata¶
内部 unicodedata
数据库已升级为使用 Unicode 11。(由 Benjamin Peterson 贡献。)
unittest¶
新的 -k
命令行选项允许按名称子字符串或类似 Unix shell 的模式过滤测试。例如,python -m unittest -k foo
运行 foo_tests.SomeTest.test_something
、bar_tests.SomeTest.test_foo
,但不运行 bar_tests.FooTest.test_something
。(由 Jonas Haag 在 bpo-32071 中贡献。)
unittest.mock¶
现在,当 sentinel
属性被 复制
或 封存
时,它们会保留其身份。(由 Serhiy Storchaka 在 bpo-20804 中贡献。)
新的 seal()
函数允许密封 Mock
实例,这将禁止进一步创建属性模拟。密封会递归地应用于所有本身是模拟的属性。(由 Mario Corchero 在 bpo-30541 中贡献。)
urllib.parse¶
urllib.parse.quote()
已从 RFC 2396 更新为 RFC 3986,将 ~
添加到默认情况下永远不会被引用的字符集中。(由 Christian Theune 和 Ratnadeep Debnath 在 bpo-16285 中贡献。)
uu¶
uu.encode()
函数现在接受一个可选的 backtick 关键字参数。当它为 true 时,零由 '`'
表示而不是空格。(由 Xiang Zhang 在 bpo-30103 中贡献。)
uuid¶
新的 UUID.is_safe
属性从平台传递有关生成的 UUID 是否使用多进程安全方法生成的信息。(由 Barry Warsaw 在 bpo-22807 中贡献。)
uuid.getnode()
现在优先使用全局管理的 MAC 地址而不是本地管理的 MAC 地址。这为从 uuid.uuid1()
返回的 UUID 的全局唯一性提供了更好的保证。如果只有本地管理的 MAC 地址可用,则返回找到的第一个。(由 Barry Warsaw 在 bpo-32107 中贡献。)
warnings¶
默认警告过滤器的初始化已更改如下:
通过命令行选项启用的警告(包括
-b
和新的 CPython 特有的-X
dev
选项)始终通过sys.warnoptions
属性传递给警告机制。通过命令行或环境启用的警告过滤器现在具有以下优先级顺序:
用于
-b
(或-bb
)的BytesWarning
过滤器使用
-W
选项指定的任何过滤器使用
PYTHONWARNINGS
环境变量指定的任何过滤器任何其他 CPython 特定的过滤器(例如,为新的
-X dev
模式添加的default
过滤器)由警告机制直接定义的任何隐式过滤器
在 CPython 调试版本 中,默认情况下会显示所有警告(隐式过滤器列表为空)
(由 Nick Coghlan 和 Victor Stinner 在 bpo-20361、bpo-32043 和 bpo-32230 中贡献。)
弃用警告再次默认显示在单文件脚本和交互式提示中。有关详细信息,请参阅 PEP 565: 在 __main__ 中显示 DeprecationWarning。(由 Nick Coghlan 在 bpo-31975 中贡献。)
xml¶
为了缓解 DTD 和外部实体检索问题,xml.dom.minidom
和 xml.sax
模块默认情况下不再处理外部实体。(由 Christian Heimes 在 gh-61441 中贡献。)
xml.etree¶
在 find()
方法中的 ElementPath 谓词现在可以将当前节点的文本与 [. = "text"]
进行比较,而不仅仅是子节点的文本。谓词还允许添加空格以提高可读性。(由 Stefan Behnel 在 bpo-31648 中贡献。)
xmlrpc.server¶
SimpleXMLRPCDispatcher.register_function
现在可以用作装饰器。(由 Xiang Zhang 在 bpo-7769 中贡献。)
zipapp¶
函数 create_archive()
现在接受一个可选的 filter 参数,允许用户选择应包含在存档中的文件。(由 Irmen de Jong 在 bpo-31072 中贡献。)
函数 create_archive()
现在接受一个可选的 compressed 参数来生成压缩的存档。还添加了一个命令行选项 --compress
来支持压缩。(由 Zhiming Wang 在 bpo-31638 中贡献。)
zipfile¶
ZipFile
现在接受新的 compresslevel 参数来控制压缩级别。(由 Bo Bayles 在 bpo-21417 中贡献。)
由 ZipFile
创建的存档中的子目录现在按字母顺序存储。(由 Bernhard M. Wiedemann 在 bpo-30693 中贡献。)
C API 更改¶
已实现用于线程局部存储的新 API。有关概述,请参阅 PEP 539:用于线程局部存储的新 C API,有关完整参考,请参阅 线程特定存储 (TSS) API。(由 Masayuki Yamamoto 在 bpo-25658 中贡献。)
新的 PyImport_GetModule()
函数返回先前导入的具有给定名称的模块。(由 Eric Snow 在 bpo-28411 中贡献。)
新的 Py_RETURN_RICHCOMPARE
宏简化了编写富比较函数的过程。(由 Petr Victorin 在 bpo-23699 中贡献。)
新的 Py_UNREACHABLE
宏可以用来标记不可达的代码路径。(由 Barry Warsaw 在 bpo-31338 中贡献。)
tracemalloc
现在通过新的 PyTraceMalloc_Track()
和 PyTraceMalloc_Untrack()
函数公开 C API。(由 Victor Stinner 在 bpo-30054 中贡献。)
新的 import__find__load__start()
和 import__find__load__done()
静态标记可用于跟踪模块导入。(由 Christian Heimes 在 bpo-31574 中贡献。)
结构体 PyMemberDef
, PyGetSetDef
, PyStructSequence_Field
, PyStructSequence_Desc
, 和 wrapperbase
的字段 name
和 doc
现在是 const char *
类型,而不是 char *
类型。(由 Serhiy Storchaka 在 bpo-28761 中贡献。)
PyUnicode_AsUTF8AndSize()
和 PyUnicode_AsUTF8()
的结果现在是 const char *
类型,而不是 char *
类型。(由 Serhiy Storchaka 在 bpo-28769 中贡献。)
PyMapping_Keys()
, PyMapping_Values()
和 PyMapping_Items()
的结果现在总是列表,而不是列表或元组。(由 Oren Milman 在 bpo-28280 中贡献。)
添加了函数 PySlice_Unpack()
和 PySlice_AdjustIndices()
。(由 Serhiy Storchaka 在 bpo-27867 中贡献。)
PyOS_AfterFork()
已被弃用,取而代之的是新函数 PyOS_BeforeFork()
, PyOS_AfterFork_Parent()
和 PyOS_AfterFork_Child()
。(由 Antoine Pitrou 在 bpo-16500 中贡献。)
作为公共 API 一部分的 PyExc_RecursionErrorInst
单例已被移除,因为它的成员从未被清除,可能会在解释器的最终化过程中导致段错误。由 Xavier de Gaye 在 bpo-22898 和 bpo-30697 中贡献。
添加了对时区的 C API 支持,包括时区构造函数 PyTimeZone_FromOffset()
和 PyTimeZone_FromOffsetAndName()
,以及通过 PyDateTime_TimeZone_UTC
访问 UTC 单例。由 Paul Ganssle 在 bpo-10381 中贡献。
PyThread_start_new_thread()
和 PyThread_get_thread_ident()
的结果类型,以及 PyThreadState_SetAsyncExc()
的 id 参数的类型从 long 更改为 unsigned long。(由 Serhiy Storchaka 在 bpo-6532 中贡献。)
如果第二个参数是 NULL
并且 wchar_t* 字符串包含空字符,PyUnicode_AsWideCharString()
现在会引发 ValueError
。(由 Serhiy Storchaka 在 bpo-30708 中贡献。)
启动序列和动态内存分配器管理方面的更改意味着,长期以来记录的要求在调用大多数 C API 函数之前调用 Py_Initialize()
现在更加依赖,不遵守可能会导致嵌入式应用程序出现段错误。有关更多详细信息,请参阅本文档中的 移植到 Python 3.7 部分和 C API 文档中的 在 Python 初始化之前 部分。
新的 PyInterpreterState_GetID()
返回给定解释器的唯一 ID。(由 Eric Snow 在 bpo-29102 中贡献。)
当启用 UTF-8 模式 时,Py_DecodeLocale()
, Py_EncodeLocale()
现在使用 UTF-8 编码。(由 Victor Stinner 在 bpo-29240 中贡献。)
PyUnicode_DecodeLocaleAndSize()
和 PyUnicode_EncodeLocale()
现在为 surrogateescape
错误处理程序使用当前区域设置编码。(由 Victor Stinner 在 bpo-29240 中贡献。)
PyUnicode_FindChar()
的 start 和 end 参数现在被调整为像字符串切片一样工作。(由 Xiang Zhang 在 bpo-28822 中贡献。)
构建更改¶
已删除对构建 --without-threads
的支持。 threading
模块现在始终可用。(由 Antoine Pitrou 在 bpo-31370 中贡献。)
在非 OSX UNIX 平台上构建 _ctypes
模块时,不再捆绑 libffi 的完整副本。 在此类平台上构建 _ctypes
时,现在需要安装 libffi 的副本。(由 Zachary Ware 在 bpo-27979 中贡献。)
Windows 构建过程不再依赖 Subversion 来拉取外部源,而是使用 Python 脚本从 GitHub 下载 zip 文件。 如果在系统上找不到 Python 3.6(通过 py -3.6
),则使用 NuGet 下载 32 位 Python 的副本用于此目的。(由 Zachary Ware 在 bpo-30450 中贡献。)
ssl
模块需要 OpenSSL 1.0.2 或 1.1 兼容的 libssl。OpenSSL 1.0.1 已于 2016-12-31 达到生命周期结束,不再受支持。LibreSSL 也暂时不受支持。LibreSSL 版本直至 2.6.4 都缺少所需的 OpenSSL 1.0.2 API。
性能优化¶
通过将更多代码移植到使用 METH_FASTCALL
约定,显著减少了调用 C 中实现的各种标准库类的许多方法的开销。(由 Victor Stinner 在 bpo-29300, bpo-29507, bpo-29452, 和 bpo-29286 中贡献。)
各种优化措施使 Linux 上的 Python 启动时间减少了 10%,macOS 上减少了高达 30%。(由 Victor Stinner, INADA Naoki 在 bpo-29585 中,以及 Ivan Levkivskyi 在 bpo-31333 中贡献。)
由于字节码的更改避免了创建绑定方法实例,方法调用现在快了 20%。(由 Yury Selivanov 和 INADA Naoki 在 bpo-26110 中贡献。)
asyncio
模块为常用函数进行了许多显著的优化。
asyncio.get_event_loop()
函数已用 C 重新实现,使其速度提高了 15 倍。(由 Yury Selivanov 在 bpo-32296 中贡献。)asyncio.Future
回调管理已得到优化。(由 Yury Selivanov 在 bpo-32348 中贡献。)asyncio.gather()
现在快了 15%。(由 Yury Selivanov 在 bpo-32355 中贡献。)当 *delay* 参数为零或负数时,
asyncio.sleep()
现在快了 2 倍。(由 Andrew Svetlov 在 bpo-32351 中贡献。)降低了 asyncio 调试模式的性能开销。(由 Antoine Pitrou 在 bpo-31970 中贡献。)
由于 PEP 560 的工作,typing
的导入时间减少了 7 倍,并且许多类型操作现在更快了。(由 Ivan Levkivskyi 在 bpo-32226 中贡献。)
sorted()
和 list.sort()
针对常见情况进行了优化,速度提高了 40-75%。(由 Elliot Gorokhovsky 在 bpo-28685 中贡献。)
dict.copy()
现在快了 5.5 倍。(由 Yury Selivanov 在 bpo-31179 中贡献。)
当找不到 *name* 且 *obj* 不覆盖 object.__getattr__()
或 object.__getattribute__()
时,hasattr()
和 getattr()
现在快了大约 4 倍。(由 INADA Naoki 在 bpo-32544 中贡献。)
在字符串中搜索某些 Unicode 字符(如乌克兰大写字母“Є”)的速度比搜索其他字符慢 25 倍。现在最坏情况下只慢 3 倍。(由 Serhiy Storchaka 在 bpo-24821 中贡献。)
collections.namedtuple()
工厂已重新实现,使命名元组的创建速度提高了 4 到 6 倍。(由 Jelle Zijlstra 贡献,并由 INADA Naoki、Serhiy Storchaka 和 Raymond Hettinger 进一步改进,见 bpo-28638。)
date.fromordinal()
和 date.fromtimestamp()
在常见情况下现在快了 30%。(由 Paul Ganssle 在 bpo-32403 中贡献。)
由于使用了 os.scandir()
,os.fwalk()
函数现在快了 2 倍。(由 Serhiy Storchaka 在 bpo-25996 中贡献。)
由于使用了 os.scandir()
函数,shutil.rmtree()
函数的速度提高了 20-40%。(由 Serhiy Storchaka 在 bpo-28564 中贡献。)
优化了 正则表达式
的不区分大小写的匹配和搜索。现在搜索某些模式的速度可以快 20 倍。(由 Serhiy Storchaka 在 bpo-30285 中贡献。)
如果 flags
参数是 RegexFlag
,re.compile()
现在会将它转换为 int 对象。现在它的速度与 Python 3.5 一样快,并且根据模式的不同,比 Python 3.6 快约 10%。(由 INADA Naoki 在 bpo-31671 中贡献。)
在重负载下,selectors.EpollSelector
、selectors.PollSelector
和 selectors.DevpollSelector
类的 modify()
方法可能会快 10% 左右。(由 Giampaolo Rodola’ 在 bpo-30014 中贡献。)
常量折叠已从窥孔优化器移至新的 AST 优化器,该优化器能够更一致地执行优化。(由 Eugene Toder 和 INADA Naoki 在 bpo-29469 和 bpo-11549 中贡献。)
abc
中的大多数函数和方法都已用 C 重写。这使得创建抽象基类以及在其上调用 isinstance()
和 issubclass()
的速度提高了 1.5 倍。这也使 Python 启动时间减少了高达 10%。(由 Ivan Levkivskyi 和 INADA Naoki 在 bpo-31333 中贡献。)
通过在不构造子类时使用快速路径构造函数,显著提高了 datetime.date
和 datetime.datetime
的备用构造函数的速度。(由 Paul Ganssle 在 bpo-32403 中贡献。)
在某些情况下,array.array
实例的比较速度得到了显著提高。当比较保存相同整数类型值的数组时,速度现在快了 10 到 70 倍。(由 Adrian Wielgosik 在 bpo-24700 中贡献。)
math.erf()
和 math.erfc()
函数现在在大多数平台上使用(更快的)C 库实现。(由 Serhiy Storchaka 在 bpo-26121 中贡献。)
其他 CPython 实现更改¶
跟踪钩子现在可以选择不接收
line
,而是通过设置帧上相应的新的f_trace_lines
和f_trace_opcodes
属性,从解释器接收opcode
事件。(由 Nick Coghlan 在 bpo-31344 中贡献。)修复了命名空间包模块属性的一些一致性问题。命名空间模块对象现在有一个
__file__
属性,其值设置为None
(之前未设置),并且它们的__spec__.origin
也被设置为None
(之前是字符串"namespace"
)。请参阅 bpo-32305。此外,命名空间模块对象的__spec__.loader
被设置为与__loader__
相同的值(之前,前者被设置为None
)。请参阅 bpo-32303。locals()
字典现在按照变量定义的词法顺序显示。之前,顺序是未定义的。(由 Raymond Hettinger 在 bpo-32690 中贡献。)distutils
upload
命令不再尝试将 CR 行尾字符更改为 CRLF。这修复了 sdist 以等效于 CR 的字节结尾时的损坏问题。(由 Bo Bayles 在 bpo-32304 中贡献。)
已弃用的 Python 行为¶
yield 表达式(包括 yield
和 yield from
子句)现在在推导式和生成器表达式中已被弃用(最左侧 for
子句中的可迭代表达式除外)。这确保了推导式总是立即返回适当类型的容器(而不是可能返回一个 生成器迭代器 对象),而生成器表达式不会尝试将其隐式输出与任何显式 yield 表达式的输出交错。在 Python 3.7 中,此类表达式在编译时会发出 DeprecationWarning
,在 Python 3.8 中,这将是一个 SyntaxError
。(由 Serhiy Storchaka 在 bpo-10544 中贡献。)
从 object.__complex__()
返回 complex
的子类已被弃用,并且在未来的 Python 版本中将引发错误。这使得 __complex__()
与 object.__int__()
和 object.__float__()
一致。(由 Serhiy Storchaka 在 bpo-28894 中贡献。)
已弃用的 Python 模块、函数和方法¶
aifc¶
aifc.openfp()
已被弃用,将在 Python 3.9 中删除。请改用 aifc.open()
。(由 Brian Curtin 在 bpo-31985 中贡献。)
asyncio¶
直接 await
-ing asyncio.Lock
和其他 asyncio 同步原语的实例的支持已被弃用。必须使用异步上下文管理器才能获取和释放同步资源。(由 Andrew Svetlov 在 bpo-32253 中贡献。)
asyncio.Task.current_task()
和 asyncio.Task.all_tasks()
方法已被弃用。(由 Andrew Svetlov 在 bpo-32250 中贡献。)
collections¶
在 Python 3.8 中,collections.abc
中的抽象基类将不再在常规 collections
模块中公开。这将有助于在具体类和抽象基类之间建立更清晰的区别。(由 Serhiy Storchaka 在 bpo-25988 中贡献。)
dbm¶
dbm.dumb
现在支持读取只读文件,并且在索引文件未更改时不再写入索引文件。如果索引文件丢失并在 'r'
和 'w'
模式下重新创建,则现在会发出弃用警告(这在未来的 Python 版本中将是一个错误)。(由 Serhiy Storchaka 在 bpo-28847 中贡献。)
enum¶
在 Python 3.8 中,尝试在 Enum
类中检查非 Enum 对象将引发 TypeError
(例如 1 in Color
);类似地,尝试在 Flag
成员中检查非 Flag 对象将引发 TypeError
(例如 1 in Perm.RW
);目前,这两个操作都返回 False
。(由 Ethan Furman 在 bpo-33217 中贡献。)
gettext¶
在 gettext
中使用非整数值选择复数形式现在已被弃用。它从来没有正确地工作过。(由 Serhiy Storchaka 在 bpo-28692 中贡献。)
importlib¶
方法 MetaPathFinder.find_module()
(由 MetaPathFinder.find_spec()
替换)和 PathEntryFinder.find_loader()
(由 PathEntryFinder.find_spec()
替换)都在 Python 3.4 中被弃用,现在会发出 DeprecationWarning
。(由 Matthias Bussonnier 在 bpo-29576 中贡献。)
importlib.abc.ResourceLoader
ABC 已被弃用,转而支持 importlib.abc.ResourceReader
。
locale¶
locale.format()
已被弃用,请改用 locale.format_string()
。(由 Garvit 在 bpo-10379 中贡献。)
macpath¶
macpath
现在已被弃用,将在 Python 3.8 中删除。(由 Chi Hsuan Yen 在 bpo-9850 中贡献。)
threading¶
dummy_threading
和 _dummy_thread
已被弃用。不再可能在禁用线程的情况下构建 Python。请改用 threading
。(由 Antoine Pitrou 在 bpo-31370 中贡献。)
socket¶
在 socket.htons()
和 socket.ntohs()
中,静默截断参数值已被弃用。在未来的 Python 版本中,如果传递的参数大于 16 位,将引发异常。(由 Oren Milman 在 bpo-28332 中贡献。)
ssl¶
ssl.wrap_socket()
已被弃用。请改用 ssl.SSLContext.wrap_socket()
。(由 Christian Heimes 在 bpo-28124 中贡献。)
sunau¶
sunau.openfp()
已被弃用,将在 Python 3.9 中删除。请改用 sunau.open()
。(由 Brian Curtin 在 bpo-31985 中贡献。)
sys¶
已弃用 sys.set_coroutine_wrapper()
和 sys.get_coroutine_wrapper()
。
未公开的 sys.callstats()
函数已被弃用,并将在未来的 Python 版本中删除。(由 Victor Stinner 在 bpo-28799 中贡献。)
wave¶
wave.openfp()
已被弃用,并将在 Python 3.9 中删除。请改用 wave.open()
。(由 Brian Curtin 在 bpo-31985 中贡献。)
C API 中已弃用的函数和类型¶
函数 PySlice_GetIndicesEx()
已被弃用,如果未设置 Py_LIMITED_API
,或设置为 0x03050400
和 0x03060000
(不包含) 之间的值,或者为 0x03060100
或更高版本,则会用宏替换。(由 Serhiy Storchaka 在 bpo-27867 中贡献。)
PyOS_AfterFork()
已被弃用。请改用 PyOS_BeforeFork()
,PyOS_AfterFork_Parent()
或 PyOS_AfterFork_Child()
。(由 Antoine Pitrou 在 bpo-16500 中贡献。)
平台支持移除¶
不再正式支持 FreeBSD 9 及更早版本。
为了完全支持 Unicode,包括在扩展模块中,现在期望 *nix 平台至少提供
C.UTF-8
(完整区域设置)、C.utf8
(完整区域设置)或UTF-8
(仅LC_CTYPE
区域设置)中的一个,作为基于旧的ASCII
的C
区域设置的替代方案。不再支持 OpenSSL 0.9.8 和 1.0.1,这意味着在仍然使用这些版本的较旧平台上构建具有 SSL/TLS 支持的 CPython 3.7 需要自定义构建选项,这些选项链接到更新版本的 OpenSSL。
值得注意的是,此问题会影响 Debian 8(又名“jessie”)和 Ubuntu 14.04(又名“Trusty”)LTS Linux 发行版,因为它们默认仍使用 OpenSSL 1.0.1。
Debian 9(“stretch”)和 Ubuntu 16.04(“xenial”)以及其他 LTS Linux 发行版的最新版本(例如 RHEL/CentOS 7.5、SLES 12-SP3)使用 OpenSSL 1.0.2 或更高版本,并且在默认构建配置中仍然受支持。
CPython 自己的 CI 配置文件 提供了一个示例,说明如何在 CPython 的测试套件中使用 SSL 兼容性测试基础设施,以构建和链接到 OpenSSL 1.1.0 而不是过时的系统提供的 OpenSSL。
API 和功能移除¶
以下功能和 API 已从 Python 3.7 中删除
os.stat_float_times()
函数已被删除。它是在 Python 2.3 中引入的,用于与 Python 2.2 向后兼容,并且自 Python 3.1 起已弃用。在
re.sub()
的替换模板中,由'\'
和 ASCII 字母组成的未知转义字符在 Python 3.5 中已弃用,现在将导致错误。删除了
tarfile.TarFile.add()
中对 exclude 参数的支持。它在 Python 2.7 和 3.2 中已弃用。请改用 filter 参数。ntpath.splitunc()
函数在 Python 3.1 中已弃用,现在已删除。请改用splitdrive()
。collections.namedtuple()
不再支持 verbose 参数或显示命名元组类生成的源代码的_source
属性。这是旨在加快类创建速度的优化的一部分。(由 Jelle Zijlstra 贡献,并由 INADA Naoki、Serhiy Storchaka 和 Raymond Hettinger 进一步改进,在 bpo-28638 中。)函数
bool()
、float()
、list()
和tuple()
不再接受关键字参数。int()
的第一个参数现在只能作为位置参数传递。删除了
plistlib
模块中以前在 Python 2.4 中已弃用的类Plist
、Dict
和_InternalDict
。函数readPlist()
和readPlistFromBytes()
的结果中的 Dict 值现在是普通的 dict。您不能再使用属性访问来访问这些字典的项。asyncio.windows_utils.socketpair()
函数已被删除。请改用socket.socketpair()
函数,它自 Python 3.5 起在所有平台上都可用。asyncio.windows_utils.socketpair
只是 Python 3.5 及更高版本中socket.socketpair
的别名。asyncio
不再将selectors
和_overlapped
模块导出为asyncio.selectors
和asyncio._overlapped
。将from asyncio import selectors
替换为import selectors
。现在禁止直接实例化
ssl.SSLSocket
和ssl.SSLObject
对象。这些构造函数从未被记录、测试或设计为公共构造函数。用户应该使用ssl.wrap_socket()
或ssl.SSLContext
。(由 Christian Heimes 在 bpo-32951 中贡献。)已删除未使用的
distutils
install_misc
命令。(由 Eric N. Vander Weele 在 bpo-29218 中贡献。)
模块移除¶
fpectl
模块已被删除。它从未默认启用,在 x86-64 上从未正确工作,并且它以导致 C 扩展意外中断的方式更改了 Python ABI。(由 Nathaniel J. Smith 在 bpo-29137 中贡献。)
仅限 Windows 的更改¶
python 启动器 (py.exe) 可以接受 32 位和 64 位说明符,而无需同时指定次要版本。因此,py -3-32
和 py -3-64
以及 py -3.7-32
都变为有效,并且现在接受 -m-64 和 -m.n-64 形式,以强制使用 64 位 python,即使本来会使用 32 位。如果指定的版本不可用,py.exe 将错误退出。(由 Steve Barnes 在 bpo-30291 中贡献。)
可以使用 py -0
运行启动器,以生成已安装 Python 的列表,默认版本会用星号标记。运行 py -0p
将包含路径。如果 py 运行时使用了无法匹配的版本指定符,它还会打印可用指定符的简短形式列表。(由 Steve Barnes 在 bpo-30362 中贡献。)
移植到 Python 3.7¶
本节列出了之前描述的更改和其他可能需要更改代码的错误修复。
Python 行为的更改¶
async
和await
名称现在是保留关键字。将这些名称用作标识符的代码现在会引发SyntaxError
。(由 Jelle Zijlstra 在 bpo-30406 中贡献。)PEP 479 在 Python 3.7 的所有代码中启用,这意味着在协程和生成器中直接或间接引发的
StopIteration
异常会被转换为RuntimeError
异常。(由 Yury Selivanov 在 bpo-32670 中贡献。)object.__aiter__()
方法不能再声明为异步。(由 Yury Selivanov 在 bpo-31709 中贡献。)由于疏忽,早期 Python 版本错误地接受了以下语法
f(1 for x in [1],) class C(1 for x in [1]): pass
Python 3.7 现在会正确引发
SyntaxError
,因为生成器表达式必须始终直接位于一组括号内,并且两侧都不能有逗号,并且只有在调用时才能省略括号的重复。(由 Serhiy Storchaka 在 bpo-32012 和 bpo-32023 中贡献。)当使用
-m
开关时,初始工作目录现在被添加到sys.path
中,而不是一个空字符串(它在每次导入时动态表示当前工作目录)。任何检查空字符串或以其他方式依赖先前行为的程序都需要进行相应的更新(例如,通过同时检查os.getcwd()
或os.path.dirname(__main__.__file__)
,具体取决于代码最初检查空字符串的原因)。
Python API 的更改¶
socketserver.ThreadingMixIn.server_close()
现在会等待所有非守护线程完成。将新的socketserver.ThreadingMixIn.block_on_close
类属性设置为False
以获得 3.7 之前的行为。(由 Victor Stinner 在 bpo-31233 和 bpo-33540 中贡献。)socketserver.ForkingMixIn.server_close()
现在会等待所有子进程完成。将新的socketserver.ForkingMixIn.block_on_close
类属性设置为False
以获得 3.7 之前的行为。(由 Victor Stinner 在 bpo-31151 和 bpo-33540 中贡献。)locale.localeconv()
函数现在在某些情况下会临时将LC_CTYPE
区域设置设置为LC_NUMERIC
的值。(由 Victor Stinner 在 bpo-31900 中贡献。)如果 path 是字符串,
pkgutil.walk_packages()
现在会引发ValueError
。之前会返回一个空列表。(由 Sanyam Khurana 在 bpo-24744 中贡献。)string.Formatter.format()
的格式字符串参数现在是仅位置参数。在 Python 3.5 中,将其作为关键字参数传递已被弃用。(由 Serhiy Storchaka 在 bpo-29193 中贡献。)类
http.cookies.Morsel
的属性key
、value
和coded_value
现在是只读的。在 Python 3.5 中,赋值给它们已被弃用。使用set()
方法来设置它们。(由 Serhiy Storchaka 在 bpo-29192 中贡献。)os.makedirs()
的 mode 参数不再影响新创建的中间层目录的文件权限位。要设置它们的文件权限位,可以在调用makedirs()
之前设置 umask。(由 Serhiy Storchaka 在 bpo-19930 中贡献。)struct.Struct.format
类型现在是str
而不是bytes
。(由 Victor Stinner 在 bpo-21071 中贡献。)cgi.parse_multipart()
现在接受 encoding 和 errors 参数,并返回与FieldStorage
相同的结果:对于非文件字段,与键关联的值是字符串列表,而不是字节。(由 Pierre Quentel 在 bpo-29979 中贡献。)由于
socket
的内部更改,不支持在旧版本 Python 中使用socket.share
创建的套接字上调用socket.fromshare()
。BaseException
的repr
已更改为不包括尾随逗号。大多数异常都会受到此更改的影响。(由 Serhiy Storchaka 在 bpo-30399 中贡献。)datetime.timedelta
的repr
已更改为在输出中包含关键字参数。(由 Utkarsh Upadhyay 在 bpo-30302 中贡献。)由于
shutil.rmtree()
现在使用os.scandir()
函数实现,当列出目录失败时,用户指定的处理程序 onerror 现在会使用第一个参数os.scandir
而不是os.listdir
调用。未来可能会添加对正则表达式中嵌套集合和集合运算的支持,如 Unicode 技术标准 #18 所述。 这将会改变语法。 为了方便未来的这种变更,目前在有歧义的情况下会引发
FutureWarning
警告。 这包括以字面量'['
开头的集合,或包含字面字符序列'--'
,'&&'
,'~~'
和'||'
的集合。 要避免警告,请使用反斜杠转义它们。(由 Serhiy Storchaka 在 bpo-30349 中贡献。)使用可能匹配空字符串的
正则表达式
分割字符串的结果已更改。 例如,使用r'\s*'
分割现在不仅会像以前一样在空白处分割,还会在所有非空白字符之前以及字符串末尾之前分割空字符串。 可以通过将模式更改为r'\s+'
来恢复以前的行为。 自 Python 3.5 起,对于此类模式会发出FutureWarning
警告。对于同时匹配空字符串和非空字符串的模式,在其他情况下搜索所有匹配项的结果也可能发生变化。 例如,在字符串
'a\n\n'
中,模式r'(?m)^\s*?$'
不仅会匹配位置 2 和 3 的空字符串,还会匹配位置 2-3 的字符串'\n'
。 要仅匹配空行,应将模式重写为r'(?m)^[^\S\n]*$'
。re.sub()
现在会替换与前一个非空匹配项相邻的空匹配项。 例如,re.sub('x*', '-', 'abxd')
现在返回'-a-b--d-'
而不是'-a-b-d-'
('b' 和 'd' 之间的第一个减号替换 'x',第二个减号替换 'x' 和 'd' 之间的空字符串)。更改
re.escape()
为仅转义正则表达式特殊字符,而不是转义除 ASCII 字母、数字和'_'
以外的所有字符。(由 Serhiy Storchaka 在 bpo-29995 中贡献。)tracemalloc.Traceback
帧现在按从旧到新的顺序排序,以便与traceback
更加一致。(由 Jesse Bakker 在 bpo-32121 中贡献。)在支持
socket.SOCK_NONBLOCK
或socket.SOCK_CLOEXEC
位标志的操作系统上,socket.type
不再应用它们。 因此,像if sock.type == socket.SOCK_STREAM
这样的检查在所有平台上都可以按预期工作。(由 Yury Selivanov 在 bpo-32331 中贡献。)在 Windows 上,当重定向标准句柄时,
subprocess.Popen
的 *close_fds* 参数的默认值从False
更改为True
。 如果您之前依赖于在使用带有标准 I/O 重定向的subprocess.Popen
时继承句柄,则必须传递close_fds=False
以保留之前的行为,或使用STARTUPINFO.lpAttributeList
。importlib.machinery.PathFinder.invalidate_caches()
– 这会隐式影响importlib.invalidate_caches()
– 现在会删除sys.path_importer_cache
中设置为None
的条目。(由 Brett Cannon 在 bpo-33169 中贡献。)在
asyncio
中,loop.sock_recv()
、loop.sock_sendall()
、loop.sock_accept()
、loop.getaddrinfo()
、loop.getnameinfo()
已更改为适当的协程方法,以匹配其文档。 以前,这些方法返回asyncio.Future
实例。(由 Yury Selivanov 在 bpo-32327 中贡献。)asyncio.Server.sockets
现在返回服务器套接字的内部列表的副本,而不是直接返回它。(由 Yury Selivanov 在 bpo-32662 中贡献。)Struct.format
现在是str
实例,而不是bytes
实例。(由 Victor Stinner 在 bpo-21071 中贡献。)现在可以通过将
required=True
传递给ArgumentParser.add_subparsers()
来使argparse
子解析器成为强制性的。(由 Anthony Sottile 在 bpo-26510 中贡献。)ast.literal_eval()
现在更加严格。 不再允许对任意数字进行加法和减法运算。(由 Serhiy Storchaka 在 bpo-31778 中贡献。)当日期超出
0001-01-01
到9999-12-31
范围时,Calendar.itermonthdates
现在将一致地引发异常。 为了支持无法容忍此类异常的应用程序,可以使用新的Calendar.itermonthdays3
和Calendar.itermonthdays4
。 新方法返回元组,并且不受datetime.date
支持的范围的限制。(由 Alexander Belopolsky 在 bpo-28292 中贡献。)collections.ChainMap
现在保留基础映射的顺序。(由 Raymond Hettinger 在 bpo-32792 中贡献。)现在,如果在解释器关闭期间调用
concurrent.futures.ThreadPoolExecutor
和concurrent.futures.ProcessPoolExecutor
的submit()
方法,则会引发RuntimeError
异常。(由 Mark Nemec 在 bpo-33097 中贡献。)现在,
configparser.ConfigParser
构造函数使用read_dict()
来处理默认值,使其行为与解析器的其余部分保持一致。现在,默认字典中的非字符串键和值会被隐式转换为字符串。(由 James Tocknell 在 bpo-23835 中贡献。)删除了几个未公开的内部导入。一个例子是
os.errno
不再可用;请直接使用import errno
代替。请注意,这种未公开的内部导入可能会在任何时候被删除,即使在微版本发布中也是如此,恕不另行通知。
C API 中的更改¶
函数 PySlice_GetIndicesEx()
被认为对于可调整大小的序列是不安全的。如果切片索引不是 int
的实例,而是实现 __index__()
方法的对象,则在将序列的长度传递给 PySlice_GetIndicesEx()
后,可以调整序列的大小。这可能导致返回超出序列长度的索引。为了避免可能的问题,请使用新的函数 PySlice_Unpack()
和 PySlice_AdjustIndices()
。(由 Serhiy Storchaka 在 bpo-27867 中贡献。)
CPython 字节码更改¶
有两个新的操作码:LOAD_METHOD
和 CALL_METHOD
。(由 Yury Selivanov 和 INADA Naoki 在 bpo-26110 中贡献。)
删除了 STORE_ANNOTATION
操作码。(由 Mark Shannon 在 bpo-32550 中贡献。)
仅限 Windows 的更改¶
用于覆盖 sys.path
的文件现在名为 <python-executable>._pth
,而不是 'sys.path'
。有关更多信息,请参阅 查找模块。(由 Steve Dower 在 bpo-28137 中贡献。)
其他 CPython 实现更改¶
为了准备将来可能对公共 CPython 运行时初始化 API 进行的更改(有关最初但有些过时的草案,请参阅PEP 432),CPython 的内部启动和配置管理逻辑已进行了重大重构。虽然这些更新旨在对嵌入应用程序和常规 CPython CLI 的用户完全透明,但这里提到它们是因为重构更改了解释器启动期间各种操作的内部顺序,因此可能会发现以前潜在的缺陷,无论是嵌入应用程序还是 CPython 本身。(最初由 Nick Coghlan 和 Eric Snow 作为 bpo-22257 的一部分贡献,并由 Nick、Eric 和 Victor Stinner 在其他一些问题中进一步更新)。一些受影响的已知细节
由于需要在调用
Py_Initialize
之前创建 Unicode 对象,因此嵌入应用程序当前无法使用PySys_AddWarnOptionUnicode()
。请改用PySys_AddWarnOption()
。嵌入应用程序使用
PySys_AddWarnOption()
添加的警告过滤器现在应比解释器设置的默认过滤器具有更高的优先级
由于默认警告过滤器的配置方式发生了更改,将 Py_BytesWarningFlag
设置为大于 1 的值已不足以既发出 BytesWarning
消息,又将其转换为异常。相反,必须设置标志(以导致首先发出警告),并添加显式的 error::BytesWarning
警告过滤器以将其转换为异常。
由于编译器处理文档字符串的方式发生了更改,仅包含文档字符串的函数体中的隐式 return None
现在被标记为与文档字符串在同一行出现,而不是在函数的标题行出现。
当前的异常状态已从帧对象移动到协程。这简化了解释器,并修复了在进入或退出生成器时交换异常状态导致的一些不明显的错误。(由 Mark Shannon 在 bpo-25612 中贡献。)
Python 3.7.1 中的显著更改¶
从 3.7.1 开始,Py_Initialize()
现在始终读取并尊重与 Py_Main()
相同的全部环境设置(在早期的 Python 版本中,它尊重那些环境变量的定义不明确的子集,而在 Python 3.7.0 中,由于 bpo-34247,它没有读取任何环境变量)。如果不需要此行为,请在调用 Py_Initialize()
之前将 Py_IgnoreEnvironmentFlag
设置为 1。
在 3.7.1 中,上下文变量的 C API 已更新为使用 PyObject
指针。另请参阅 bpo-34762。
在 3.7.1 中,tokenize
模块现在会在提供没有尾随换行符的输入时隐式发出 NEWLINE
令牌。此行为现在与 C 令牌分析器在内部执行的操作匹配。(由 Ammar Askar 在 bpo-33899 中贡献。)
Python 3.7.2 中的显著更改¶
在 3.7.2 中,Windows 上的 venv
不再复制原始二进制文件,而是创建名为 python.exe
和 pythonw.exe
的重定向器脚本。这解决了长期存在的问题,即每次 Python 更新都必须升级或重新创建所有虚拟环境。但是,请注意,此版本仍然需要重新创建虚拟环境才能获取新脚本。
Python 3.7.6 中的显著更改¶
由于存在严重的安全问题,不再支持 asyncio.loop.create_datagram_endpoint()
的 reuse_address 参数。这是因为 UDP 中的套接字选项 SO_REUSEADDR
的行为。有关更多详细信息,请参阅 loop.create_datagram_endpoint()
的文档。(由 Kyle Stanley、Antoine Pitrou 和 Yury Selivanov 在 bpo-37228 中贡献。)
Python 3.7.10 中的显著更改¶
早期版本的 Python 允许在 urllib.parse.parse_qs()
和 urllib.parse.parse_qsl()
中使用 ;
和 &
作为查询参数分隔符。出于安全考虑,并为了符合最新的 W3C 建议,此行为已更改为仅允许使用单个分隔符,默认使用 &
。此更改也会影响 cgi.parse()
和 cgi.parse_multipart()
,因为它们内部使用了受影响的函数。有关更多详细信息,请参阅它们各自的文档。(由 Adam Goldschmidt、Senthil Kumaran 和 Ken Jin 在 bpo-42967 中贡献。)
Python 3.7.11 中的重要更改¶
一个安全修复程序更改了 ftplib.FTP
的行为,使其在设置被动数据通道时不信任远程服务器发送的 IPv4 地址。我们改为重用 ftp 服务器 IP 地址。对于需要旧行为的非常规代码,请在您的 FTP 实例上设置一个 trust_server_pasv_ipv4_address
属性为 True
。(请参阅 gh-87451)
URL 的某些部分中存在换行符或制表符可能会导致某些形式的攻击。按照更新 RFC 3986 的 WHATWG 规范,解析器 urllib.parse()
会从 URL 中删除 ASCII 换行符 \n
、\r
和制表符 \t
字符,以防止此类攻击。删除的字符由新的模块级变量 urllib.parse._UNSAFE_URL_BYTES_TO_REMOVE
控制。(请参阅 gh-88048)
3.7.14 中的重要安全功能¶
在 2(二进制)、4、8(八进制)、16(十六进制)或 32 以外的基数(例如 10(十进制))之间转换 int
和 str
时,如果字符串形式的数字位数超过限制,现在会引发 ValueError
,以避免由于算法复杂性而导致的潜在拒绝服务攻击。这是针对 CVE 2020-10735 的缓解措施。此限制可以通过环境变量、命令行标志或 sys
API 进行配置或禁用。请参阅整数字符串转换长度限制文档。字符串形式的默认限制为 4300 位数字。