Python程序的执行原理(1)(2)
test.py的指令序列
func函数的指令序列
第一列表示以下几个指令在py文件中的行号;
第二列是该指令在指令序列co_code里的偏移量;
第三列是指令opcode的名称,分为有操作数和无操作数两种,opcode在指令序列中是一个字节的整数;
第四列是操作数oparg,在指令序列中占两个字节,基本都是co_consts或者co_names的下标;
第五列带括号的是操作数说明。
7. 执行字节码
Python虚拟机的原理就是模拟可执行程序再X86机器上的运行,X86的运行时栈帧如下图:
假如test.py用C语言来实现,会是下面这个样子:
- const char *s = “hello”;
- void func() {
- printf(“%s\n”, s);
- }
- int main() {
- func();
- return 0;
- }
Python虚拟机的原理就是模拟上述行为。当发生函数调用时,创建新的栈帧,对应Python的实现就是PyFrameObject对象。
7.1 PyFrameObject
- typedef struct _frame {
- PyObject_VAR_HEAD
- struct _frame *f_back; /* 调用者的帧 */
- PyCodeObject *f_code; /* 帧对应的字节码对象 */
- PyObject *f_builtins; /* 内置名字空间 */
- PyObject *f_globals; /* 全局名字空间 */
- PyObject *f_locals; /* 本地名字空间 */
- PyObject **f_valuestack; /* 运行时栈底 */
- PyObject **f_stacktop; /* 运行时栈顶 */
- …….
- }
那么对应Python的运行时栈就是这样子:
7.2 执行指令
执行test.py的字节码时,会先创建一个栈帧,以下用f表示当前栈帧,执行过程注释如下:
test.py的符号名集合和常量集合
- co.co_names (‘s’, ’func’)
- co.co_consts (‘hello’, <code object func at 0x2aaeeec57110, file ”test.py”, line 3>, None)
test.py的指令序列
上面的CALL_FUNCTION指令执行时,会创建新的栈帧,并执行func的字节码指令,以下用f表示当前栈帧,func的字节码执行过程如下:
func函数的符号名集合和常量集合
- func.co_names (‘s’,)
- func.co_consts (None,)
评论关闭