Python 3.14(πthon)中的最佳新功能和修复内容
摘要:随着Python 3.14发布,带来多项重要更新:正式支持自由线程,消除GIL限制;新增实验性JIT编译器,提升性能;Windows系统安装管理工具改进;引入模板字符串(t-string)增强文本处理;优化类型注释延迟评估机制;错误提示更智能;新增安全调试接口和C配置API;标准库支持多解释器并发;解释器底层优化尾调用编译。这些改进在性能、并发、开发者体验等方面带来显著提升,同时保持向后兼容。
Python 3.14 现已全面推出。本文介绍了 Python 下一版本中最重要的新功能及其对 Python 开发者的意义。
以下是 Python 3.14 中最重要的新特性:
- 对自由线程的官方支持,以及自由线程方面的改进
- 实验性的即时编译器
- 适用于微软 Windows 系统的新的 Python 安装管理器
- 模板字符串
- 注释的延迟评估
- 更完善的错误提示信息
- 对 CPython 的安全外部调试器接口
- Python 运行时配置的 C API
- 对多个解释器的支持的内置标准库
- “尾调用编译”解释器
- 增量垃圾回收
- 异步程序的内省功能
- Emscripten 现在已成为 Python 的官方支持平台
自由线程的官方支持及改进
Python 的自由线程版本承诺通过消除全局解释器锁(GIL)为 Python 程序中的线程实现真正的并行性。然而,最初它被视为一个需要获得更大规模的 Python 社区支持的实验性项目。尽管自由线程版本与 Python 3.13 一同发布,但您必须选择使用它,并且当时没有官方支持。
在 Python 3.14 版本中,免费多线程版本仍会随 Python 安装一同提供,并且仍需用户选择启用,但如今它已被视为 Python 的官方支持版本。这意味着免费多线程版的 Python 将继续作为 Python 的常规组成部分一同发布,并且不会在没有适当弃用计划的情况下被移除。
自 Python 3.13 版本以来,Python 的自由线程功能有了显著的改进。之前用于提升 Python 性能的一种机制(专门化自适应解释器)在自由线程构建中并未启用,但现在它是可用的了。自由线程的一个持续性问题是,在单线程程序上的性能较差,这类程序的运行速度通常比在支持全局解释器锁(GIL)的构建版本中慢 5%至 10%。这种性能损失在不同平台上以及针对不同程序时会有所差异,因此值得在两个构建版本上测试您的应用程序,以了解其优势或劣势。
实验性的即时编译器
增强 Python 性能的另一项新功能是即时编译器,即 JIT。该 JIT 是针对专门化自适应解释器的一种补充,通过将单个字节码替换为类型特定的版本来加快 Python 的运行速度。与专门化自适应解释器相比,JIT 更具雄心的优化能力,它会将整串字节码指令替换为预先生成的机器代码段。
在 Python 3.14 版本中,即时编译功能已可在 Microsoft Windows 和 macOS 系统的 CPython 二进制版本中启用,但默认情况下处于禁用状态,因为该功能仍被视为实验性特性。可以通过环境变量(PYTHON_JIT=1)或命令行标志来启用它。与单线程构建一样,可以在自己的工作负载上试验即时编译功能,但不要期望能获得一致的性能提升。实际上,在这个阶段,可能会发现性能反而会下降,而非提升。
请注意,即时编译功能目前尚未在单线程构建版本中实现。目前可以选择启用其中的一项功能,但不能同时启用两项。
适用于 Windows 系统的全新 Python 安装管理器
在微软 Windows 系统上安装 Python 一直以来都是通过一个安装工具来完成的,但该工具并非总能成功管理多个版本的 Python 的安装。如果习惯于添加和删除不同版本的 Python 并同时运行它们,那么该 Windows 版的 Python 安装程序有时可能会破坏较旧版本的行为。
Python 的维护人员为 Windows 系统开发了一款全新的 Python 安装管理工具。从外观上看,它与原版 Python 安装程序的运作方式非常相似:运行它,它会安装指定版本的 Python。但该工具还具备更强大的功能,能够删除或更新所有先前安装的版本,设置哪个版本作为默认版本,并为特定的 Python 命令或程序调用特定版本。
模板字符串
在 Python 中,我们长期以来一直使用 f-string 来方便地将变量格式化到字符串中。Python 3.14 引入了这一系列功能中的更高级特性,即根据 PEP 750 定义的模板字符串。
模板字符串(或简称“t字符串”)允许您将模板与一个作用于模板结构而非仅作用于其输出的函数相结合。我们可以编写一个模板处理程序,使其能够在输出时对模板中放置的所有变量、特定类型的变量,或者与某些输出相匹配的变量进行操作。还可以将变量和插值文本作为不同的、不同类型的对象进行处理。
例如,如果模板是 “My name is {name}, and I’m from {country}.”,那么可以让变量 “name” 和 “country” 在显示之前自动清除掉任何 HTML 内容。您还可以对输出中的 “My name is” 和 "and I’m from” 部分进行自动转换,因为这些部分会被标记为特殊的“插值”类型。
模板字符串将使编写模板引擎(例如 Jinja2)变得容易得多,或者能够直接在 Python 中复制这些模板引擎的大部分功能,而无需借助第三方库所带来的额外开销。
注释的延迟评估
在 Python 中,类型注释过去通常是“立即”进行评估的,即在代码首次遇到它们时就进行评估。这种做法使得实现诸如类型的前向引用之类的功能变得困难。例如,要有一个类方法,该方法接收一个参数,而这个参数的类型是通过暗示另一个尚未在模块中定义的类型来指定的:
class Thing:def frob(self, other:OtherThing):...
class OtherThing:...
像这样的代码通常无法通过代码检查工具的检测。解决办法可以是:
class Thing:def frob(self, other:"OtherThing"):...
class OtherThing:...
或者可以使用 “from future import annotations” 这一语句。
在 Python 3.14 版本中,对象的注释信息现在存储在“注释函数”中,这些注释函数可通过一个名为“annotate”的属性访问。该属性在需要时会返回给定对象的注释信息,因此注释可以由代码检查工具延迟计算,甚至可以在运行时进行计算。
“annotationlib” 模块提供了用于在运行时或作为代码检查流程的一部分来检查这些新注释的工具。
如果目前是通过“from future import annotations”来解决延迟注释问题的,那么目前无需进行任何更改。不过,此指令已被弃用,并且在未来版本的 Python 中将会完全被移除(很可能在 2029 年之后)。
更完善的错误提示信息
在过去的几次 Python 版本更新中,错误提示信息在多个方面都得到了改进和优化。这一传统在 Python 3.14 版本中也得以延续。
最大的改进在于:那些与 Python 关键字高度相似的未知术语现在会给出相关建议。例如:
forr a in b:
^^^^
SyntaxError: invalid syntax. Did you mean 'for'?
此外,还进行了多项错误修正的优化工作:
- 在解包操作中出现的问题,即预期数量与实际接收数量不一致的情况,现在在更多情况下会有更详细的错误提示。
- elif 代码块位置错误会自动生成特定的错误信息。
- 非法地将三元赋值和控制流结合使用(例如,x = a if b else pass)的语句现在会生成详细的错误提示。
- 字符串格式错误时会给出补全字符串的建议。
一个安全的 CPython 外部调试器接口
将外部调试器附加到 CPython 解释器上会带来大量的运行时开销以及潜在的安全问题。此外,无法自行将调试器附加到 CPython 上。要使用外部调试器,就必须在启动 CPython 时就将调试器附加上去。
在 Python 3.14 版本中,新增了一个调试器接口,它为 CPython 解释器提供了连接点,使得能够无需更改其执行流程就附加调试器。可以使用 Python 的 pdb 调试模块来附加到另一个 Python 进程(通过其进程 ID),并在目标进程中进行交互式调试,而无需在附加调试器后重新启动该进程。
除了带来更多的便利之外,新的调试器界面还使得第三方能够更轻松地开发出更出色、更可靠的调试工具。他们将不再需要将自己编写的自定义代码注入解释器中,因为这样可能会导致代码变得脆弱并引发新的错误。
用于 Python 运行时配置的 C API
Python 配置 C API 提供了一个 C 语言接口,允许用户通过 Python 对象而非 C 结构体来设置或获取有关 Python 解释器当前配置的信息。这样,就可以直接从 Python 本身来配置解释器,从而更方便地编写 Python 级别的工具来对解释器的行为进行运行时更改。
Python 的配置 C API 是对 CPython 内部结构和 API 进行整体清理的一部分,其中包括 CPython 的初始化相关 API。请注意,如果 C 语言用户需要的话,他们始终可以回退使用更低级别的 API。
使用 except 处理多种异常的更简便方法
如果想在 try/except 块中捕获多种异常,就必须使用括号将它们括起来:
try:flaky_function()
except (BigProblem, SmallProblem):...
在 Python 3.14 版本中,可以直接通过逗号将多个异常列举出来:
try:flaky_function()
except BigProblem, SmallProblem:...
原有的语法仍然有效,不过新的语法在处理常见情况时能减少一些输入操作。
标准库对多个解释器的支持
Python 一直以来都有多种用于并发编程的选项:线程、进程处理以及异步编程。最近,一个长期处于休眠状态的功能经过改进,变得对最终用户非常有用:在单个进程中支持多个解释器实例。
长期以来,"子解释器"系统一直没有真正的用户界面。从 Python 3.14 版本开始,Python 标准库中新增了一个名为 “concurrent.interpreters” 的模块,该模块提供了使用子解释器的一些基本功能。这为实现与多进程的完全隔离以及线程的共享上下文之间的一种中间状态提供了支持。
目前,concurrent.interpreters 这个模块并没有提供太多的功能。例如,没有很多用于在不同解释器之间共享对象的高级机制,而且子解释器的工作方式与线程或子进程的工作方式通常并不相同。因此,子解释器应被视为一种用于并发的实验性新机制,随着其功能的逐步完善,Python 社区将会发现其最佳的应用场景。
“尾调用编译”解释器
在 Python 3.14 中,CPython 解释器可以利用 C 代码中函数之间的尾调用这一特性。如果使用支持这些特性的 C 编译器进行编译,CPython 的运行速度会稍快一些。请注意,此特性与在 Python 语言中启用尾调用优化并非同一回事;它是 CPython 解释器的内部优化。Python 开发者只需升级到 Python 3.14 即可获得此优势。
不幸的是,此次更改所预期的性能提升结果与实际情况大相径庭,这是因为 Clang/LLVM19 编译器中存在一个错误(该错误已在后续版本中得到修复)。性能提升幅度在 3% 到 5% 之间,远低于最初报告的 9% 至 15% 的速度提升。与任何此类优化一样,开发人员需要自行进行基准测试,以了解应用程序的实际性能表现。
增量式垃圾回收
CPython 的垃圾回收器已进行了重新设计,采用了增量式回收方式以提高性能。此前,对象在进行垃圾回收时可被追踪到多达三个不同的代,这取决于它们的存活时间长短。现在,垃圾回收器仅使用两个代,即年轻代和老年代。每次垃圾回收过程会处理整个年轻世代以及一部分老年世代。其结果是垃圾回收暂停时间大幅缩短,有时甚至能缩短至原来的 1/10 左右。
异步编程的内省特性
检查异步任务的运行时行为一直都不容易。现在,Python 提供了一个命令行函数 “python -m asyncio ps <process_id>”,通过提供被检查的 Python 程序的解释器进程标识符,可以查看其当前正在执行的异步任务的相关信息。此功能的一个主要优点是,它无需为被检查的程序添加任何监控代码,也无需停止正在运行的程序来添加检查代码。我们可以从任何当前运行的 Python 3.14 程序中获取此功能。
Emscripten 已成为 Python 的官方支持平台
Emscripten 可将 C/C++ 代码编译为 WebAssembly,并且已被用于将许多来自不同生态系统的程序移植到 Wasm 运行时环境中。例如,Rust 语言通过 Emscripten 以 Wasm 为目标。通过 PEP 776,Python 现在将 Emscripten 作为“三级”平台纳入支持范围,与 Apple iOS 的 Arm64 和 Android 的 x86-64 一起并列。这意味着在 Emscripten/Wasm 上运行的 Python 具有可靠的自动化构建系统,并且至少有一位核心开发人员将继续支持该平台。这也意味着,今后在该平台上构建失败不会阻碍后续的发布。简而言之,虽然 WebAssembly 可能无法完全支持其他平台上的所有功能,但 Python 3.14 增加了对一些此前不支持的库的支持,例如 ctypes。