本文档全面概述了 CPython 的代码执行管道——Python 源代码被转换为可执行指令并随后执行的过程。该管道包括解析、编译、优化和执行阶段,这些阶段协同工作以高效地运行 Python 程序。
有关管道特定阶段的实现细节,请参阅 编译管道、字节码解释器与优化。
CPython 代码执行管道包含多个阶段,可将 Python 源代码转换为运行的软件
来源: Python/compile.c1-14 Python/ceval.c1-47 Python/bytecodes.c1-41 Python/optimizer.c1-22
编译阶段通过一系列明确定义的步骤将 Python 源代码转换为字节码
来源: Python/compile.c107-148 Python/flowgraph.c75-106 Python/symtable.c1-34
在代码生成之前,会创建一个符号表来跟踪变量及其作用域。此分析有助于确定哪些名称是局部、全局、非局部或闭包变量
来源: Python/symtable.c91-108 Python/compile.c138-146
代码生成阶段将 AST 转换为中间指令序列
来源: Python/compile.c1-17 Python/codegen.c1-10 Python/flowgraph.c66-87 Python/assemble.c1-5
Python 字节码由虚拟机执行的操作(操作码)和参数(操作数)组成
| 组件 | 描述 |
|---|---|
co_code | 字节码指令序列(每条 2 字节) |
co_consts | 代码中使用的常量元组 |
co_names | 代码中引用的名称元组 |
co_varnames | 局部变量名元组 |
co_freevars | 自由变量名元组 |
co_cellvars | 单元变量名元组 |
CPython 使用分层执行模型
来源: Python/bytecodes.c76-146 Python/generated_cases.c.h1-30 Python/ceval.c500-535 Python/optimizer.c100-154
基线解释器直接执行字节码指令。它通过 _PyEval_EvalFrameDefault 函数运行,该函数在一个循环中处理每个指令
字节码指令在 bytecodes.c 中使用结构化格式定义,并经过处理以生成解释器 switch case
inst(LOAD_FAST, (-- value)) {
assert(!PyStackRef_IsNull(GETLOCAL(oparg)));
value = PyStackRef_DUP(GETLOCAL(oparg));
}
来源: Python/bytecodes.c268-277 Python/generated_cases.c.h21-81 Python/ceval.c30-46
CPython 采用各种专业化技术来优化执行
| 专业化类型 | 示例 |
|---|---|
| 基于类型 | BINARY_OP_ADD_INT 用于整数加法 |
| 基于值 | LOAD_CONST_IMMORTAL 用于不朽对象 |
| 基于形状 | LOAD_ATTR_INSTANCE_VALUE 用于直接实例属性访问 |
来源: Python/bytecodes.c583-621 Python/bytecodes.c295-333
Tier 2 执行系统使用基于跟踪的优化来提高性能
来源: Python/optimizer.c100-154 Python/executor_cases.c.h1-74 Include/internal/pycore_uop_ids.h1-20
优化器将字节码指令分解为更小的微操作 (UOps),它们代表更细粒度的操作
例如,BINARY_OP 指令可以分解为像 _BINARY_OP_ADD_INT 这样的专用 UOps
case _BINARY_OP_ADD_INT: {
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
assert(PyLong_CheckExact(left_o));
assert(PyLong_CheckExact(right_o));
STAT_INC(BINARY_OP, hit);
PyObject *res_o = _PyLong_Add((PyLongObject *)left_o, (PyLongObject *)right_o);
PyStackRef_CLOSE_SPECIALIZED(right, _PyLong_ExactDealloc);
PyStackRef_CLOSE_SPECIALIZED(left, _PyLong_ExactDealloc);
// ...
}
来源: Python/executor_cases.c.h175-199 Python/bytecodes.c626-664
Tier 2 优化器执行数据流分析,以跟踪跟踪中的变量值和类型
来源: Python/optimizer_analysis.c1-32 Python/optimizer_cases.c.h106-157
Guard 是特殊指令,用于验证优化过程中所做的假设
来源: Python/optimizer_cases.c.h107-148 Python/optimizer_bytecodes.c107-142
在 Python 3.13+ 中,正在开发一项实验性的即时(Just-In-Time)编译器,用于将优化后的跟踪转换为本地机器码
字节码执行流水线支持用于调试、分析和监控的插桩
来源: Python/instrumentation.c1-32 Python/instrumentation.c74-107
CPython 代码执行流水线是一个复杂的系统,通过多个编译和优化阶段将 Python 源代码转换为运行中的程序。通过使用具有专用指令的分层执行方法、基于跟踪的优化以及潜在的 JIT 编译,CPython 能够高效地执行 Python 代码,同时保持语言的灵活性和动态性。
了解此流水线有助于开发人员优化其 Python 代码,并通过针对执行堆栈的适当层进行改进来为 CPython 本身做出贡献。