[笔记]Python虚拟机如何执行“i = 1”

首先写一个demo.py,里面只有一句:

i = 1

接着写一个test.py,内容如下:

import dis

source = open('./demo.py').read()
co = compile(source, './demo.py', 'exec')

dis.dis(co)

输出:

  1           0 LOAD_CONST               0 (1)
              3 STORE_NAME               0 (i)
              6 LOAD_CONST               1 (None)
              9 RETURN_VALUE  

利用Python库提供的dis工具,可以对其反汇编,得到如上结果(开头的1表示对应的源码行号)。

所以,对于i = 1这样的语句,Python的虚拟机是一步一步执行上述指令的。

PyEval_EvalFrameEx是通过switch/case语句来执行指令的,对应的LOAD_CONST代码如下:

       case LOAD_CONST:
            x = GETITEM(consts, oparg);
            Py_INCREF(x);
            PUSH(x);
            goto fast_next_opcode;

consts是指PyCodeObject中的常量:consts = co->co_consts;

首先是从consts常量元组中获取元素,oparg为0,即获取((PyTupleObject *)op)
-> ob_item[i];。

接着增加引用计数。

然后将其压栈:

#define BASIC_PUSH(v)     (*stack_pointer++ = (v))
#define PUSH(v)         { (void)(BASIC_PUSH(v), \
……

这里的stack_pointer是帧(活动记录)对应的栈指针:stack_pointer = f->f_stacktop;

所以执行到这里,就是从consts变量元组中取出第0个元素(值为1),将其push到当前活动记录对应的栈中。

接下来是LOAD_VALUE:

      case STORE_NAME:
            w = GETITEM(names, oparg);
            v = POP();
            if ((x = f->f_locals) != NULL) {
                if (PyDict_CheckExact(x))
                    err = PyDict_SetItem(x, w, v);
                else
                    err = PyObject_SetItem(x, w, v);
                Py_DECREF(v);
                if (err == 0) continue;
                break;
            }
            PyErr_Format(PyExc_SystemError,
                         "no locals found when storing %s",
                         PyObject_REPR(w));
            break;

首先从names中取出第0个元素,即i;

接着进行出栈操作,把刚才进展的1给POP出来;

最后把键值对(key - value)保存到局部符号表中:f->f_locals。

最后两句是返回语句。


JasonLee     2011.08.21     15:08

时间: 2025-01-30 05:41:26

[笔记]Python虚拟机如何执行“i = 1”的相关文章

[笔记]Python虚拟机对创建基本内置对象的执行过程

同样的,有demo.py代码如下: i = 1 s = "Python" d = {"1":1, "2":2} l = [2, 3] 有test.py代码如下: import dis source = open('./demo.py').read() co = compile(source, './demo.py', 'exec') dis.dis(co) 输出如下: 1 0 LOAD_CONST 0 (1) 3 STORE_NAME 0 (i)

[笔记]Python虚拟机对函数的解释

demo.py: i = 1 def f(): j = 2 f() test.py: import dis source = open('./demo.py').read() co = compile(source, './demo.py', 'exec') print(co.co_name) dis.dis(co) print("\n") fCode = co.co_consts[1] print(fCode.co_name) dis.dis(fCode) 输出: <modul

[笔记]Python虚拟机对if语句的解释

demo.py代码如下: a = 1 if a > 0: pass elif a == 0: pass else: pass test.py代码如下: import dis source = open('./demo.py').read() co = compile(source, './demo.py', 'exec') dis.dis(co) 输出结果如下: 1 0 LOAD_CONST 0 (1) 3 STORE_NAME 0 (a) 2 6 LOAD_NAME 0 (a) 9 LOAD_

Python程序的执行原理

1. 过程概述 Python先把代码(.py文件)编译成字节码,交给字节码虚拟机,然后虚拟机一条一条执行字节码指令,从而完成程序的执行. 2. 字节码 字节码在Python虚拟机程序里对应的是PyCodeObject对象. .pyc文件是字节码在磁盘上的表现形式. 3. pyc文件 PyCodeObject对象的创建时机是模块加载的时候,即import. Python test.py会对test.py进行编译成字节码并解释执行,但是不会生成test.pyc. 如果test.py加载了其他模块,如

Python虚拟机的初始化概览

今天想跟下Python虚拟机的启动,看看以调试模式跑起python_d.exe是怎么一个过程. 1. d:\Python-2.7.2\Modules\python.c文件是main函数,直接调用Py_Main函数: 2. 在Py_Main函数中,初始化函数为Py_Initialize();,而后者直接调用Py_InitializeEx(1);函数: 3. 在Py_InitializeEx函数中,首先判断是否已经初始化过,如果有则返回,没有就改下标志,开始初始化:第一步也是十分关键的一步,是调用函

scrapy笔记——python的时间转换

  1 import datetime 2 GMT_FORMAT = '%M %H %d %m %w' 3 datetime.datetime.utcnow().strftime(GMT_FORMAT)   1 #按corn格式显示当前时间 2 #minute hour day month dayofweek 3 import datetime 4 CORN_FORMAT = '%M %H %d %m %w' 5 datetime.datetime.utcnow().strftime(CORN_

初步探究Python程序的执行原理_python

1. 过程概述 Python先把代码(.py文件)编译成字节码,交给字节码虚拟机,然后虚拟机一条一条执行字节码指令,从而完成程序的执行.2. 字节码 字节码在Python虚拟机程序里对应的是PyCodeObject对象. .pyc文件是字节码在磁盘上的表现形式.3. pyc文件 PyCodeObject对象的创建时机是模块加载的时候,即import. Python test.py会对test.py进行编译成字节码并解释执行,但是不会生成test.pyc. 如果test.py加载了其他模块,如im

从底层简析Python程序的执行过程

  这篇文章主要介绍了从底层简析Python程序的执行过程,包括注入操作码和封装程序等解释器执行层面的知识,需要的朋友可以参考下 最近我在学习 Python 的运行模型.我对 Python 的一些内部机制很是好奇,比如 Python 是怎么实现类似 YIELDVALUE.YIELDFROM 这样的操作码的;对于 递推式构造列表(List Comprehensions).生成器表达式(generator expressions)以及其他一些有趣的 Python 特性是怎么编译的;从字节码的层面来看

python连接mysql执行source命令出错。。

问题描述 python连接mysql执行source命令出错.. 如这张图片所示.百思不得其解中..求大神指教.. 解决方案 你的sql文件是否有语法错误,你直接mysql命令行能source执行成功?