Python 3.14 新特性学习(第二部分)

前一篇 Python 3.14 新特性学习(第一部分) 基本就是被 Python 3.14 标准库的多解释器霸屏,所以另起一篇继续 What's new in Python 3.14 中其他几个重要新特性。

PEP 765: finally 代码块中的控制流

编译器在检测到 finally 代码块存在 return, break, 或 continue 语句, 会触发 SyntaxWarning. 原因也很简单, 可以反问自己一句, 在 finally 放上 return, break, 或 continue 语句想干什么, 还想跳出 finally 语句块?

用 Python 3.13 和 3.14 测试下面的代码

分别用 python3.13 和 python3.14 执行

$python3.13 test.py
$python3.14 test.py
test.py:5: SyntaxWarning: 'return' in a 'finally' block
return

Python 3.14 以前不会有任何警告,但代码的执行结果是对的,只是在 return 后的代码是无效且多余的.

except 和 except* 捕获多个异常时可省略圆括号

以上代码在 Python 3.13 中报错

except KeyError, ValueError:
             ^^^^^^^^^^^^^^^
SyntaxError: multiple exception types must be parenthesized

必须写成

然而当要在 except 中 as ex 时要引用捕获到的异常时, 不管是 Python 3.13 还是 Python 3.14 又得把括号加回去

写成 except KeyError, ValueError as ex: 语法是错误的。一般情况下捕获到的异常都会要做点什么事情,看来这种改进不能带来多少实效。

PEP 768: 安全的外部调试器接口

该特性会给 IDE 工具,或远程调试带来便利,相对应的命令是 python -m pdb -p 1234。本节中以下内容直接摘自:https://docs.python.org/zh-cn/3.14/whatsnew/3.14.html#whatsnew314-remote-debugging

Python 3.14 引入了一个零开销的调试接口,它允许调试器和性能分析工具安全地附加到正在运行的 Python 进程而不会停止或重启它们。 这显著加强了 Python 的调试能力,意味着不安全的替代方案已不再需要。

新的接口为附加调试器代码提供了安全的执行点而无需修改解释器的正常执行路径或增加任何运行时开销。 因此,相关工具现在可以实时地对 Python 应用程序进行检查和交互,这对于高可用性系统和生产环境来说是非常关键的能力。

出于便捷性考虑,本接口是在 sys.remote_exec() 函数中实现的。

自由线程模式的改进

Python 3.14 对自由线程模式进行了改进,这是不能直接感受到的,自由线程已经转正,非实验性的,不过仍为可选,所以默认仍有 GIL。想要获得自由线程的 Python 仍然需要通过源代码,用 --disable-gil 编译选项禁用 GIL 构建自己的二进制版本,官方并未直接提供相应的二进制安装文件。

uv 的话,可直接安装到开启了自由线程(禁用了 GIL) 的 Python 版本,如在 mac OS 下

$ uv python install 3.14t
Installed Python 3.14.0rc2 in 6.86s
  + cpython-3.14.0rc2+freethreaded-macos-aarch64-none (python3.14t)
$ python3.14t
Python 3.14.0rc2 free-threading build (main, Sep 2 2025, 14:17:48) [Clang 20.1.4 ] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys._is_gil_enabled()
False

用命令 uv python list --only-downloads 可查看可下载的所有 Python 二进制版本,尚未看到标注了 JIT 的版本。

二进制版本提供了选的 JIT 支持

官方提供的 macOS 和  Windows 平台的 Python 二进制版提供了可选的 JIT 支持,用 PYTHON_JIT=1 开启,默认未开启,自己构建的话用 --enable-experimental-jit=yes-off 编译选项。实际中请自行谨慎评估使用。

在本机用 brew install python@3.14 安装的 Python 3.14 试了下

用上  JIT 带来性能改善可能为 -10% ~ +20%,因地制宜吧。

PEP 649 和 PEP 749: 标注的迟延求值

在 Java 中 Annotation, 即 @Value 的形式,是注解的意思,而 Python 的标注(Annotation,但中文翻译通常不称作注解) 是指 typing hints -- 类型提示,Python 中的 @value 形式的语法有个不同的名词,叫做装饰器(Decoration)。

Python 是动态类型的语言,解释器一直不要求静态类型,但它在版本演进当中又在不停的就 typing 方式增强类型标注,在规范利用类型提示的情况下,再结合 mypy, pytype, pyright, ruff 等工具的检查,可用 Python 写出伪强类型风格的代码。再有一些 Python 框架,如 FastAPI 在某些时候依赖于类型标注,尽管如此,Python 也没有发展出一个 TypeScript 之于 JavaScript 那样的真静态语言。

Python 标注的延迟早在 Python 3.7(PEP 563) 就有增强,比如下面这段代码

在 Python 3.7 中有语法错误,报的错误是

NameError: name 'Tree' is not defined

因为在定义 __init__(self, left: Tree, right: Tree) 是,Tree 还没有完全创建出来,所以还不能引用,但是只要提前引入

from __future__ import annotations

就没问题了,因为达成了 Tree 的延迟求值

在 Python 3.6 中无法引入 from __future__ import annotations, 因为它不存在。而发展到 Python 3.8 及之后,这句引入 annotations 的都能省去了。

回到 Python 3.14,看它对延迟(即需要时)求值有了什么更新的动作。

它的大致实现是在对象上新加了一个 dunder(双下划线 - double underscore) 属性 __annotate__, 解释代码时把标注暂放到该属性中,运行时再从中取出相应标拿出来求值而体现在 __annotations__(该属性于 Python 3.0 就有)。也就是 Python 的对象标注是由它的 __annotations__ 属性描述的。

比如下面的代码

在 Python 3.13 中无法执行,错误为

NameError: name 'MyType' is not defined

但在最前面加上

from __future__ import annotations

就没问题了,仿佛 Python 对 Annotation 的演进就是一直在尽力去除该行 from __future__ import annotations 代码, 该引入的功能是为了转换所有的标注为字符串的形式。from __future__ import annotations 将会在 Python 3.13 生命周期结束后删除,因此以后尽量不使用它。

打印 foo.__annotations__ 的内容为

{'x': <class 'int'>, 'y': <class '__main__.MyType'>, 'return': <class 'float'>}

那么问题又来了,Python 3.14 知道推迟到运行时来求 MyType 的类型,那么 mypy 那种纯静态检查的工具能理解得了吗?答案是,不行

用 pip install mypy 安装的版本为 mypy-1.18.2

$ mypy test_annotation.py
test.py:3: error: Incompatible default for argument "y" (default has type "None", argument has type "MyType") [assignment]
test.py:3: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True
test.py:3: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase
Found 1 error in 1 file (checked 1 source file)

前面有 from __future__ import annotations 也是一样的错误,看来 mypy 也得适配才行,不能仅满足于纯静态检测。

对象的 __annotations__ 是可读写的,所以通过定制其中的值也能影响到对象的实际标类型,并可用 inspect.get_annotations(foo), typing.get_type_hits(foo) 获取到实际的注解类型

可是这样做又有什么意义呢?因为 IDE 是大概率是无法提示出 y 是 'MyType' 类型,或者返回值是 float 而非 None.

调用 foo.__annotate__(1) 或  foo.__annotate__(2) 都会看到

{'x': <class 'int'>, 'y': <class '__main__.MyType'>, 'return': <class 'float'>}

好,具体的实现细节就不继续深挖了。

现在有了一个新的库 annotationlib 用来替代的 inspect 的相关功能,如

annotationlib.get_annotations(foo, format=[Format.VALUE | Format.FORWARDREF | Format.STRING])

Python 的类型标注系统是由 annotation 和 typing 两个部件来支撑的,在 annotationlib 中还提供了更多的辅助方法,对于接近于元编程的人员才会有详细了解的需求。

标注的延迟求值也体现在 REPL 中,如

a: X | None = None

在 Python 3.13 中会出错

NameError: name 'X' is not defined

在 Python 3.14 中就没问题,可以在后面声明一个 class X: ...

其他一些特性

下面快速罗列一下其余的新特性

  1. 改进的错误信息显示 -- 好像一直在改进,不用特别关注,用了就知道
  2. 新模块 compression 支持各种压缩算法,如 compression.lzma, compression.bz2 compression.gzip, compression.zlib 等,新代码要使用到压缩的话,尽量使用 compression 模块,而非 import gzip 那样。compression.zstd 是新压缩算法,对 Zstandard 的支持也加入到了 tarfile, zipfile, 和  shutil 模块当中。
  3. 新的 python -m asyncio ps PIDpython -m asyncio pstree PID 用于诊断正在运行当中的 asyncio 程序,如某些 Python Web 框架应用
  4. 增强式垃圾回收, 对于较大的堆内在,最大停顿时间将减少一个数级或更多。Python 也用了分代(新生代和老年代)收集,不知道是不是 Python 从一开始垃圾回收算法就实现的特别出色,因为隔壁 Java 的垃圾回收算法不断的在改进,而 Python 垃圾回收的话题不多。
  5. python -m calendar 会以彩色高亮标记当前日期, 这个 calendar  模块就像是 mac OS 下  cal -y 命令显示的内容,所以基本不会用到它
  6. python -m http.server 可通过 --tls-cert, --tls-key, --tls-password-file 等参数,由 http.server.HTTPSServer 类支持 HTTPS 服务
  7. 提供了新的 python -m json ... 命令,可对 json 数据进行简单的处理,并且在控制台下以彩色高亮显示 JSON 内容
    usage: python3.14 -m json [-h] [--sort-keys] [--no-ensure-ascii] [--json-lines] [--indent INDENT | --tab | --no-indent | --compact] [infile] [outfile]
  8. ctypes.util.dllist() 可列举当前已加载的动态库

本文链接 https://yanbin.blog/python-3-14-new-features-2/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

guest

0 Comments
Inline Feedbacks
View all comments