time

tkinter

traceback — 回溯

typing

主要的变化,请参阅 有关类型提示的新增特性

unicodedata

unittest

venv

  • 当新的 Python 虚拟环境被创建时,将使用 venv sysconfig 安装方案 来确定环境内部的路径。 当 Python 在虚拟环境中运行时,同一个安装方案将被设为默认。 这意味着下游分发方可以修改默认的 sysconfig 安装方案而不会改变虚拟环境的行为。 同样会创建新的虚拟环境的第三方代码也应当这样做。 (由 Miro Hrončok 在 bpo-45413 [https://bugs.python.org/issue?@action=redirect&bpo=45413] 中贡献。)

warnings

zipfile

性能优化

本节列出的特定优化均不依赖于 更快的 CPython 项目,后者将在其专属章节中列出。

更快的 CPython

平均而言 CPython 3.11 比 CPython 3.10 快 25% [https://github.com/faster-cpython/ideas#published-results],该数据是用 pyperformance [https://github.com/python/pyperformance] 基准测试套件测得的,基于 Ubuntu Linux 上的 GCC 编译版。 根据工作负载的不同,总的提速效果可达 10-60%。

本项目聚焦于 Python 的两个主要领域: 更快的启动更快的运行时。 本项目未涉及的优化将在 性能优化 中单独列出。

更快的启动

冻结导入 / 静态代码对象

Python 会将 bytecode 缓存到 pycache 目录以加快模型加载的速度。

在 3.10 版本时,Python 模块执行类似于这样:

  1. 读取 __pycache__ -> marshal -> 堆分配的代码对象 -> 求值

在 Python 3.11 中,对 Python 启动具有关键影响的核心模块已被“冻结”。 这意味着它们的 代码对象 (及字节码) 将由解释器静态地分配。 这使得模块执行过程的步骤减少为:

  1. 静态分配的代码对象 -> 求值

现在 Python 3.11 解释器启动加快了 10-15%。 这对使用 Python 的短期运行程序具有显著的影响。

(由 Eric Snow, Guido van Rossum 和 Kumar Aditya 在许多问题事件中贡献。)

更快的运行时

开销更低、更为惰性的 Python 帧

存放执行信息的 Python 帧会在 Python 调用一个 Python 函数时被自动创建。 下面是新帧的优化操作:

  • 优化改进了帧创建进程。

  • 通过大量重用 C 栈上的帧空间来避免内存分配。

  • 将内部帧结构优化为仅包含关键信息。 在此之前的帧保存有额外的调试和内存管理信息。

现在旧式的 帧对象 仅在调试器或 Python 内省函数如 sys._getframe()inspect.currentframe() 发出请求时才会被创建。 对于大多数用户代码,将不会创建任何帧对象。 因此,几乎所有 Python 函数调用都有显著的提速。 我们在 pyperformance 中测得了 3-7% 的提速。

(由 Mark Shannon 在 bpo-44590 [https://bugs.python.org/issue?@action=redirect&bpo=44590] 中贡献。)

内联的 Python 函数调用

在 Python 函数调用期间,Python 将调用一个评测 C 函数来解读该函数的代码。 这会有效地将纯 Python 递归限制在 C 栈的安全范围以内。

在 3.11 中,当 CPython 检测到 Python 代码调用了另一个 Python 函数时,它会设置一个新帧,并“跳转”到新帧内部的新代码。 这可以避免全部调用 C 解析函数。

大多数 Python 函数调用现在将不消耗任何 C 栈空间,这提升了它们的速度。 在简单的递归函数如斐波那契或阶乘函数中,我们测得了 1.7x 的提速。 这还意味着递归函数能够递归得更深(如果用户通过 sys.setrecursionlimit() 提升了递归限制的话)。 我们在 pyperformance 中测得了 1-3% 的提升。

(由 Pablo Galindo 和 Mark Shannon 在 bpo-45256 [https://bugs.python.org/issue?@action=redirect&bpo=45256] 中贡献。)

PEP 659:专门化自适应解释器

PEP 659 [https://peps.python.org/pep-0659/] 是 Faster CPython 项目的关键部分之一。 基本理念在于虽然 Python 是一种动态语言,但大部分代码都存在对象和类型极少发生变化的区域。 这一理念被称为 类型稳定性

在运行时,Python 将尝试在所执行的代码中寻找常见模式和类型稳定性。 然后 Python 将把当前的操作替换为更加专门化的操作。 这种专门化的操作使用仅对这些应用场景/类型来说可用的快速路径,它们的性能通常都会超过其泛用型的对应物。 这还带来了名为 内联缓存 的另一项理念,即 Python 会将高消耗的操作的结果直接缓存在 bytecode 中。

这个特化程序还会将特定的常见指令对合并为一条超级指令,减少执行期间的开销。

Python 将只特化(会被多次执行的)“热门”代码。 这可以防止 Python 在只执行一次的代码上浪费时间。 Python 还可以在代码过于动态或用法发生变化时取消特化。 特化会定期地尝试,而特化尝试的开销也不高,这使得特化能够适应新的环境改变。

(PEP 由 Mark Shannon 撰写,部分想法由 Stefan Brunthaler 提供。 请参阅 PEP 659 [https://peps.python.org/pep-0659/] 了解详情。 由 Mark Shannon 和 Brandt Bucher 实现,并由 Irit Katriel 和 Dennis Sweeney 提供了额外的帮助。)

运算 形式 专门化 运行加速(最高) 贡献者
双目运算 x + x x - x x * x 常见类型如 int, floatstr 的双目加法、乘法和减法将采用针对其下层类型专门定制的快速路径。 10% Mark Shannon, Donghee Na, Brandt Bucher, Dennis Sweeney
下标 a[i] 对容器类型如 list, tupledict 的下标操作将直接索引下层数据结构。 对自定义 __getitem__() 的下标操作也是采用类似于 内联的 Python 函数调用 的内联方式。 10-25% Irit Katriel, Mark Shannon
存储下标操作 a[i] = z 类似于上述的下标操作专门化。 10-25% Dennis Sweeney
调用 f(arg) C(arg) 对常用内置 (C) 函数和类型如 len()str 的调用将直接调用其下层 C 版本。 这将避免经历内部调用流程。 20% Mark Shannon, Ken Jin
加载全局变量 print len 对象在全局/内置命名空间中的索引会被缓存。 加载全局和内置变量将不需要命名空间查找过程。 [1] Mark Shannon
加载属性 o.attr 类似于加载全局变量。 属性在类/对象命名空间中的索引会被缓存。 在大多数情况下,加载属性将不需要命名空间查找过程。 [2] Mark Shannon
加载要调用的方法 o.meth() 方法的实际地址会被缓存。 加载方法现在将不需要命名空间查找过程 — 即使对于具有较长继承链的类来说也是如此。 10-20% Ken Jin, Mark Shannon
存储属性 o.attr = z 类似于加载属性的优化。 2% 的运行效率 Mark Shannon
解包序列 *seq 针对常见容器如 listtuple 进行了专门化。 避免内部调用流程。 8% Brandt Bucher

[1] 类似的优化自 Python 3.8 起即已存在。 3.11 针对更多形式进行了专门化并减少了部分开销。

[2] 类似的优化自 Python 3.10 起即已存在。 3.11 针对更多形式进行了专门化。 此外,所有属性加载都应当通过 bpo-45947 [https://bugs.python.org/issue?@action=redirect&bpo=45947] 获得了加速。

杂项

常见问题

我要如何编写代码以便应用这些加速?

请编写遵循常见最佳实践的具有 Python 风格的代码;你不需要修改你的代码。 CPython 加速计划会针对我们观察到的常见代码模式进行优化。

CPython 3.11 会使用更多内存吗?

可能不会;我们预期内存占用的增加相比 3.10 不会超过 20%。 这是通过上文提及的帧对象和对象字典内存优化来平衡的。

我没有发现我的运行负载有任何加速。 为什么?

特定代码将不会有明显的收益。 如果你的代码大部时间消耗在 I/O 操作上,或者像 NumPy 那样大部分计算是在 C 扩展库中进行的就将如此。 目前这个项目将只针对纯 Python 的运行负载。

此外,pyperformance 分数是一个几何平均值。 即使在 pyperformance 基准测试内部,特定的基准测试也略有放缓,但其他的基准测试则有将近 2x 的加速!

是否有 JIT 编译器?

没有。 我们还在探索其他优化方式。

关于

CPython 加速项目探索针对 CPython 的优化。 项目主团队由 Microsoft 提供资助来支持全职工作。 Pablo Galindo Salgado 还由 Bloomberg LP 提供资助来兼职该项目。 此外,还有许多贡献者是来自社区的志愿者。

CPython 字节码的改变

字节码现在包含内联缓存条目,它采用新增的 CACHE 指令形式。 许多操作码都预期带有确切数量的缓存,并指示解释器在运行时跳过它们。 被填充的缓存看起来可以像是任意指令,因此在读取或修改包含加速的数据的原始自适应字节码时应当格外小心。

新的操作码

被替换的操作码

被替换的操作码 新增的操作码 备注
BINARY_* INPLACE_* BINARY_OP 用单个操作码替换所有数值类双目/原地操作码
CALL_FUNCTION CALL_FUNCTION_KW CALL_METHOD CALL KW_NAMES PRECALL PUSH_NULL 对方法的参数变换与关键字参数的处理进行解偶;允许更好的调用特化
DUP_TOP DUP_TOP_TWO ROT_TWO ROT_THREE ROT_FOUR ROT_N COPY SWAP 栈操纵指令
JUMP_IF_NOT_EXC_MATCH CHECK_EXC_MATCH 现在会执行检查但不会跳转
JUMP_ABSOLUTE POP_JUMP_IF_FALSE POP_JUMP_IF_TRUE JUMP_BACKWARD POP_JUMP_BACKWARD_IF_* POP_JUMP_FORWARD_IF_* 参见 [3]; 针对每个方向的 TRUE, FALSE, NONENOT_NONE 变种
SETUP_WITH SETUP_ASYNC_WITH BEFORE_WITH with 代码块设置

[3] 所有跳转操作码现在都是相对的,包括现有的 JUMP_IF_TRUE_OR_POPJUMP_IF_FALSE_OR_POP。 该参数现在是相对于当前指令的偏移量而不是绝对位置。

修改/移除的操作码

  • 修改 MATCH_CLASSMATCH_KEYS 为不再推入额外的布尔值来指示成功/失败。 而是在失败时推入 None 来代替由被提取值组成的元组。

  • 修改配合异常使用的操作码以反映它们现在是由栈上的一个条目而非三个条目代表 (参见 gh-89874 [https://github.com/python/cpython/issues/89874])。

  • 移除了 COPY_DICT_WITHOUT_KEYS, GEN_START, POP_BLOCK, SETUP_FINALLYYIELD_FROM

弃用

本小节列出了已在 Python 3.11 中弃用的 Python API。

已弃用的 C API 将 单独列出

语言/内置对象

模块

aifc

chunk

msilib

pipes

telnetlib

audioop

crypt

nis

sndhdr

uu

cgi

imghdr

nntplib

spwd

xdrlib

cgitb

mailcap

ossaudiodev

sunau

(由 Brett Cannon 在 bpo-47061 [https://bugs.python.org/issue?@action=redirect&bpo=47061] 以及 Victor Stinner 在 gh-68966 [https://github.com/python/cpython/issues/68966] 中贡献。)

标准库

  • configparser 的下列部分自 Python 3.2 起已被弃用。 现在它们的弃用警告已更新为提示它们将在 Python 3.12 中被移除:

    • configparser.SafeConfigParser

    • configparser.ParsingError.filename 特征属性

    • configparser.RawConfigParser.readfp() 方法

(由 Hugo van Kemenade 在 bpo-45173 [https://bugs.python.org/issue?@action=redirect&bpo=45173] 中贡献。)

请改用 TestLoader 方法:

(由 Erlend E. Aasland 在 bpo-5846 [https://bugs.python.org/issue?@action=redirect&bpo=5846] 中贡献。)

计划在 Python 3.12 中移除

以下 Python API 已在之前的 Python 发布版中弃用,并将在 Python 3.12 中移除。

C API 的移除计划将 单独列出

  • asynchat 模块

  • asyncore 模块

  • 整个 distutils 包

  • imp 模块

  • typing.io 命名空间

  • typing.re 命名空间

  • cgi.log()

  • importlib.find_loader()

  • importlib.abc.Loader.module_repr()

  • importlib.abc.MetaPathFinder.find_module()

  • importlib.abc.PathEntryFinder.find_loader()

  • importlib.abc.PathEntryFinder.find_module()

  • importlib.machinery.BuiltinImporter.find_module()

  • importlib.machinery.BuiltinLoader.module_repr()

  • importlib.machinery.FileFinder.find_loader()

  • importlib.machinery.FileFinder.find_module()

  • importlib.machinery.FrozenImporter.find_module()

  • importlib.machinery.FrozenLoader.module_repr()

  • importlib.machinery.PathFinder.find_module()

  • importlib.machinery.WindowsRegistryFinder.find_module()

  • importlib.util.module_for_loader()

  • importlib.util.set_loader_wrapper()

  • importlib.util.set_package_wrapper()

  • pkgutil.ImpImporter

  • pkgutil.ImpLoader

  • pathlib.Path.link_to()

  • sqlite3.enable_shared_cache()

  • sqlite3.OptimizedUnicode()

  • PYTHONTHREADDEBUG 环境变量

  • The following deprecated aliases in unittest 中的下列已弃用别名:

已弃用的别名

方法名

弃用于

failUnless

assertTrue()

3.1

failIf

assertFalse()

3.1

failUnlessEqual

assertEqual()

3.1

failIfEqual

assertNotEqual()

3.1

failUnlessAlmostEqual

assertAlmostEqual()

3.1

failIfAlmostEqual

assertNotAlmostEqual()

3.1

failUnlessRaises

assertRaises()

3.1

assert_

assertTrue()

3.2

assertEquals

assertEqual()

3.2

assertNotEquals

assertNotEqual()

3.2

assertAlmostEquals

assertAlmostEqual()

3.2

assertNotAlmostEquals

assertNotAlmostEqual()

3.2

assertRegexpMatches

assertRegex()

3.2

assertRaisesRegexp

assertRaisesRegex()

3.2

assertNotRegexpMatches

assertNotRegex()

3.5

移除

本小节列出了已在 Python 3.11 中移除的 Python API。

已移除的 C API 将 单独列出

binascii.crc_hqx() 函数仍然可用。

(由 Victor Stinner 在 bpo-45085 [https://bugs.python.org/issue?@action=redirect&bpo=45085] 中贡献。)

(由 Hugo van Kemenade 在 bpo-45320 [https://bugs.python.org/issue?@action=redirect&bpo=45320] 中贡献。)

移植到 Python 3.11

本节列出了先前描述的更改以及 Python API 中可能需要修改你的 Python 代码的其他错误修正。

针对 C API 的移植说明将 单独列出

构建变化

备注

使用环境变量 TCLTK_CFLAGSTCLTK_LIBS 来手动指定 Tcl/Tk 头文件和库的位置。 configure 选项 --with-tcltk-includes--with-tcltk-libs 已被移除。

在 RHEL 7 和 CentOS 7 上开发包将不提供 tcl.pctk.pc;请使用 TCLTK_LIBS="-ltk8.5 -ltkstub8.5 -ltcl8.5"Misc/rhel7 目录包含 .pc 文件以及如何使用 RHEL 7 和 CentOS 7 的 Tcl/Tk 和 OpenSSL 构建 Python 的说明。

  • CPython 现在将默认使用 30 比特位的数字来实现 Python int。 之前版本中,在 SIZEOF_VOID_P >= 8 的平台上默认使用 30 比特位数字,否则使用 15 位数字。 仍然有可能通过配置脚本的 --enable-big-digits 选项或 PC/pyconfig.h 中的 PYLONG_BITS_IN_DIGIT 变量(适用于 Windows)显式地要求使用 15 比特位数字,但该选项可能会在未来某个时候被移除。 (由 Mark Dickinson 在 bpo-45569 [https://bugs.python.org/issue?@action=redirect&bpo=45569] 中贡献。)

C API 的变化

新的特性

(由 Christian Heimes 在 bpo-45459 [https://bugs.python.org/issue?@action=redirect&bpo=45459] 中贡献。)

移植到 Python 3.11

带有旧版宏的 tp_dealloc 函数,例如:

  1. static void
  2. mytype_dealloc(mytype *p)
  3. {
  4. PyObject_GC_UnTrack(p);
  5. Py_TRASHCAN_SAFE_BEGIN(p);
  6. ...
  7. Py_TRASHCAN_SAFE_END
  8. }

应当按照以下方式迁移到新版宏:

  1. static void
  2. mytype_dealloc(mytype *p)
  3. {
  4. PyObject_GC_UnTrack(p);
  5. Py_TRASHCAN_BEGIN(p, mytype_dealloc)
  6. ...
  7. Py_TRASHCAN_END
  8. }

请注意 Py_TRASHCAN_BEGIN 的第二个参数应该是它所属的取消分配函数。

要在同一代码库中支持旧版本的 Python,可以定义以下的宏并在整个代码中使用它们 (版权声明:这些宏是从 mypy 代码库中拷贝的):

  1. #if PY_VERSION_HEX >= 0x03080000
  2. # define CPy_TRASHCAN_BEGIN(op, dealloc) Py_TRASHCAN_BEGIN(op, dealloc)
  3. # define CPy_TRASHCAN_END(op) Py_TRASHCAN_END
  4. #else
  5. # define CPy_TRASHCAN_BEGIN(op, dealloc) Py_TRASHCAN_SAFE_BEGIN(op)
  6. # define CPy_TRASHCAN_END(op) Py_TRASHCAN_SAFE_END(op)
  7. #endif
  1. #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE)
  2. static inline void PySET_TYPE(PyObject *ob, PyTypeObject *type)
  3. { ob->ob_type = type; }
  4. #define Py_SET_TYPE(ob, type) PySET_TYPE((PyObject*)(ob), type)
  5. #endif

(由 Victor Stinner 在 bpo-39573 [https://bugs.python.org/issue?@action=redirect&bpo=39573] 中贡献。)

  • 由于 Py_SIZE() 已改为内联静态函数,因此 Py_SIZE(obj) = new_size 必须换成 Py_SET_SIZE(obj, new_size): 参见 Py_SET_SIZE() 函数(自 Python 3.9 起可用)。 为保持向下兼容,可以使用这个宏:
  1. #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE)
  2. static inline void PySET_SIZE(PyVarObject *ob, Py_ssize_t size)
  3. { ob->ob_size = size; }
  4. #define Py_SET_SIZE(ob, size) PySET_SIZE((PyVarObject*)(ob), size)
  5. #endif

(由 Victor Stinner 在 bpo-39573 [https://bugs.python.org/issue?@action=redirect&bpo=39573] 中贡献。)

  • Py_LIMITED_API 宏被设为 0x030b0000 (Python 3.11) 或更高版本时, 将不再包含头文件 , , 。 C 扩展应在 #include 之后显式地包括头文件。 (由 Victor Stinner 在 bpo-45434 [https://bugs.python.org/issue?@action=redirect&bpo=45434] 中贡献。)

  • 非受限 API 文件 cellobject.h, classobject.h, code.h, context.h, funcobject.h, genobject.hlongintrepr.h 已被移至 Include/cpython 目录。 此外,还移除了 eval.h 头文件。 这些文件不能被直接包括,因为它们已经被包括在 Python.h 中了:参见 包括文件。如果它们已被直接包括,请考虑改为包括 Python.h。 (由 Victor Stinner 在 bpo-35134 [https://bugs.python.org/issue?@action=redirect&bpo=35134] 中贡献。)

  • PyUnicode_CHECK_INTERNED() 宏已被排除在受限 C API 之外。 它从未在那里被使用,因为它使用了受限 C API 中不可用的内部结构体。 (由 Victor Stinner 在 bpo-46007 [https://bugs.python.org/issue?@action=redirect&bpo=46007] 中贡献。)

  • 以下帧函数和类型现在可通过 #include 直接使用,不再需要添加 #include :

(由 Victor Stinner 在 gh-93937 [https://github.com/python/cpython/issues/93937] 中贡献。)

虽然文档指出 PyFrameObject 字段可能随时更改,但这些字段长期以来一直保持稳定,并在多个流行的扩展中使用。

在 Python 3.11 中,为了优化性能,对帧结构进行了重组。 一些字段被完全删除,因为它们属于旧实现的细节。

PyFrameObject 字段:

现在 Python 帧对象是惰性地创建的。 一个附带影响是 f_back 成员不可被直接访问,因为现在它的值也是惰性地计算的。 必须改为调用 PyFrame_GetBack() 函数。

直接访问 f_locals 的调试器 必须 改为调用 PyFrame_GetLocals()。 它们不再需要调用 PyFrame_FastToLocalsWithError()PyFrame_LocalsToFast(),实际上它们不应调用这些函数。 现在帧所需要的更新将由虚拟机来管理。

在 Python 3.8 及更旧版本上定义 PyFrame_GetCode() 的代码:

  1. #if PY_VERSION_HEX < 0x030900B1
  2. static inline PyCodeObject* PyFrame_GetCode(PyFrameObject *frame)
  3. {
  4. Py_INCREF(frame->f_code);
  5. return frame->f_code;
  6. }
  7. #endif

在 Python 3.8 及更旧版本上定义 PyFrame_GetBack() 的代码:

  1. #if PY_VERSION_HEX < 0x030900B1
  2. static inline PyFrameObject* PyFrame_GetBack(PyFrameObject *frame)
  3. {
  4. Py_XINCREF(frame->f_back);
  5. return frame->f_back;
  6. }
  7. #endif

或者使用 pythoncapi_compat 项目 [https://github.com/python/pythoncapi-compat] 在更旧版本的 Python 上获取这些函数。

在 Python 3.8 或更旧版本中定义 PyThreadState_GetFrame() 的代码:

  1. #if PY_VERSION_HEX < 0x030900B1
  2. static inline PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate)
  3. {
  4. Py_XINCREF(tstate->frame);
  5. return tstate->frame;
  6. }
  7. #endif

在 Python 3.10 或更旧版本中定义 PyThreadState_EnterTracing()PyThreadState_LeaveTracing() 的代码:

  1. #if PY_VERSION_HEX < 0x030B00A2
  2. static inline void PyThreadState_EnterTracing(PyThreadState *tstate)
  3. {
  4. tstate->tracing++;
  5. #if PY_VERSION_HEX >= 0x030A00A1
  6. tstate->cframe->use_tracing = 0;
  7. #else
  8. tstate->use_tracing = 0;
  9. #endif
  10. }
  11.  
  12. static inline void PyThreadState_LeaveTracing(PyThreadState *tstate)
  13. {
  14. int use_tracing = (tstate->c_tracefunc != NULL || tstate->c_profilefunc != NULL);
  15. tstate->tracing--;
  16. #if PY_VERSION_HEX >= 0x030A00A1
  17. tstate->cframe->use_tracing = use_tracing;
  18. #else
  19. tstate->use_tracing = use_tracing;
  20. #endif
  21. }
  22. #endif

或者使用 pythoncapi-compat 项目 [https://github.com/python/pythoncapi-compat] 在旧版的 Python 函数上获取这些函数。

弃用

  • 弃用以下配置 Python 初始化的函数:

    • PySys_AddWarnOptionUnicode()

    • PySys_AddWarnOption()

    • PySys_AddXOption()

    • PySys_HasWarnOptions()

    • PySys_SetArgvEx()

    • PySys_SetArgv()

    • PySys_SetPath()

    • Py_SetPath()

    • Py_SetProgramName()

    • Py_SetPythonHome()

    • Py_SetStandardStreamEncoding()

    • PySetProgramFullPath()

改用新的 Python 初始化配置PyConfig API ( PEP 587 [https://peps.python.org/pep-0587/])。 (由 Victor Stinner 在 gh-88279 [https://github.com/python/cpython/issues/88279] 中贡献。)

计划在 Python 3.12 中移除

以下 C API 在早期 Python 发行版中已经弃用,将在 Python 3.12 中移除。

  • PyUnicode_AS_DATA()

  • PyUnicode_AS_UNICODE()

  • PyUnicode_AsUnicodeAndSize()

  • PyUnicode_AsUnicode()

  • PyUnicode_FromUnicode()

  • PyUnicode_GET_DATA_SIZE()

  • PyUnicode_GET_SIZE()

  • PyUnicode_GetSize()

  • PyUnicode_IS_COMPACT()

  • PyUnicode_IS_READY()

  • PyUnicode_READY()

  • PyUnicode_WSTR_LENGTH()

  • PyUnicodeAsUnicode()

  • PyUnicode_WCHAR_KIND

  • PyUnicodeObject

  • PyUnicode_InternImmortal()

移除

  • PyFrame_BlockSetup()PyFrame_BlockPop() 已被移除。 (由 Mark Shannon 在 bpo-40222 [https://bugs.python.org/issue?@action=redirect&bpo=40222] 中贡献。)

  • 移除了下列使用 errno 变量的数学宏:

    • Py_ADJUST_ERANGE1()

    • Py_ADJUST_ERANGE2()

    • Py_OVERFLOWED()

    • Py_SET_ERANGE_IF_OVERFLOW()

    • Py_SET_ERRNO_ON_MATH_ERROR()

(由 Victor Stinner 在 bpo-45412 [https://bugs.python.org/issue?@action=redirect&bpo=45412] 中贡献。)

这些不是 受限 API 的组成部分。

(由 Victor Stinner 在 bpo-45474 [https://bugs.python.org/issue?@action=redirect&bpo=45474] 中贡献。)

  • 移除了 Py_UNICODE 编码器 API,它们从 Python 3.3 起已经弃用,很少使用,而且相对于推荐的替代品来说,效率很低。

被移除的函数有:

  • PyUnicode_Encode()

  • PyUnicode_EncodeASCII()

  • PyUnicode_EncodeLatin1()

  • PyUnicode_EncodeUTF7()

  • PyUnicode_EncodeUTF8()

  • PyUnicode_EncodeUTF16()

  • PyUnicode_EncodeUTF32()

  • PyUnicode_EncodeUnicodeEscape()

  • PyUnicode_EncodeRawUnicodeEscape()

  • PyUnicode_EncodeCharmap()

  • PyUnicode_TranslateCharmap()

  • PyUnicode_EncodeDecimal()

  • PyUnicode_TransformDecimalToASCII()

请参阅 PEP 624 [https://peps.python.org/pep-0624/] 了解细节以及 迁移指引 [https://peps.python.org/pep-0624/#alternative-apis]。 (由 Inada Naoki 在 bpo-44029 [https://bugs.python.org/issue?@action=redirect&bpo=44029] 中贡献。)

3.11.4 中的重要变化

tarfile

3.11.5 中的重要变化

OpenSSL

  • 来自 python.org 的 Windows 版本和 macOS 安装程序现在使用 OpenSSL 3.0。