PythonTip >> 博文 >> python

Python源码剖析----Python的编译结果

liushulinle 2014-11-29 15:11:16 点击: 62808 | 收藏


1. 和java类似,Python文件在真正被执行之前需要被编译成字节码文件(pyc),然后由python虚拟机执行。每个文件在改变内容之前只会被编译一次,这和java也是一样的。java的源码编译之后得到的实际上得到的是PyCodeObject对象,该对象被写入硬盘时的文件就是pyc文件。

2.并非每个python文件生成一个PyCodeObject对象,而是每个CodeBlock生成一个PyCodeObject对象。区分CodeBlock的方法是,当进入一个新的名字空间时,就进入了一个新的CodeBlock。例如:
[demo.py]
class A:
    pass
def fun():
    pass
a = A()
fun()
编译demo.py文件会生成3个PyCodeObject对象,一个对应整个文件,一个对应class A,最后一个对应函数fun

3.Python并不总是会生成pyc文件,如果直接在命令行中运行demo.py文件,会发现并没有在硬盘上生成pyc,原因可能是Python认为该段代码不会被再次执行。如果想生成其对于的pyc文件,只需要在文件头加上import demo(注意,python中可以import自己),再次运行就会生成pyc了。也就是说,import会激活生成pyc机制。

4.如果碰到import abc这样的语句时,python将到设定好的path中寻找abc.pyc或abc.dll文件,如果都没有,而只发现了abc.py, 那么python会首先将abc.py编译成相应的PyCodeObject的中间结果,然后创建abc.pyc文件,并将中间结果写入该文件。接下来Python才会进行import操作,实际上就是将abc.pyc文件中的PyCodeObject对象从内存中复制出来。

5.pyc文件的内容
实际上,pyc文件不只包含PyCodeobject对象,还包括其它信息。具体来说,包含三部分信息:
第一部分是magic_number,不同版本的python会定义不同的magic_number,这个数字是用来保证Python兼容性的。比如说,要防止Python2.5加载Python1.5产生的pyc文件,只需要将Python2.5的magic_number设置的和Python1.5不同即可
第二部分是生成pyc的时间,这个信息可以让Python自动将pyc文件与最新版本的py文件同步
最后一部分是PyCodeObject对象,

6.每个py文件只会有一个PyCodeObject对象被写入pyc文件,但是每个py文件却会生成多个PyCodeObject对象,这样会导致丢失PyCodeObject对象吗?
答案是当然不会,Python的PyCodeObject是按照CodeBlock来区分的,每个文件最外层的Codeblock包含了所有其他的CodeBlock,因此其它的PyCodeObject对象时嵌入在最外层的PyCodeObject对象中的,实际上这些子PyCodeObject对象时存储在最外层PyCodeObject对象的co_consts域中的。写入pyc文件时,遇到新的PyCodeObject会递归写入。


作者:liushulinle | 分类: python | 标签: python Python源码 | 阅读: 62808 | 发布于: 2014-11-29 15时 |