Python执行过程
Python解释器“解释”文件的时候(如python test.py),实际上是先进行一个“编译的过程”,生成PyCodeObject,就是我们说的“字节码”,之后这些字节码将在python的虚拟机上执行,而且在我们需要的时候,我们可以将编译的结果保存起来,即把PyCodeObject保存起来,这就是我们的.pyc文件,下次运行的时候就会省去“编译的过程”。
查看生成的字节码
假设现在有一个test.py
文件,文件包含简单的三行内容
x = 1
y = 2
z = x + y
我们可以在python解释器中使用compile函数来得到code object(也就是在C层面的PyCodeObject)
c = compile(open('test.py').read(), 'test.py', 'exec')
得到的结果如图,可以通过它的co_code
属性获得一个字符串,这就是“编译”得到的字节码
![](https://img.haomeiwen.com/i11053934/494d250c25bbf05c.png)
直接展示出来的是字符串形式的,我们拿到他们对应的数值:
![](https://img.haomeiwen.com/i11053934/3ba40fbf9b295490.png)
现在看起来它还是没有什么意义,但是一会我们就可以找到它们的意义了,在此之前,我们以一种更为直观的形式来查看这些字节码,通过使用python的dis模块,在解释器中使用dis.dis(c)
或者直接使用python -m dis test.py
命令运行dis查看编译test.py产生的字节码,输出结果为:
![](https://img.haomeiwen.com/i11053934/0c01cc8a477e6330.png)
最一边代表的是源代码行数(test.py共三行代码),第二列代表的是字节码指令的偏移或者说是它在字节码序列中的位置,第三列代表的就是字节码指令的名字,第四列就是参数,但它只是一个储存在栈中的位置,括号中的才是它对应的实际值。
此时,我们再去看Include/opcode.h文件,我们只截取两行
![](https://img.haomeiwen.com/i11053934/7d160aa2b72b7d44.png)
这时我们就可以和之前的一串数字对上了,第一条指令为LOAD_CONST,对应值为100,参数为0,这就对应了最前面的两个数100、1,这一个指令初始位置是0,我们跳跃到第三行代码对应的位置,找到偏移为10的LOAD_NAME指令,参数为1,对应了第十个和第十一个数字101、1,事实上dis就是通过code object的一些信息结合opcode.h来以更形象的方式展现字节码的
至此,我们算是查看到了字节码,第一篇文章大功告成。
网友评论