Python程序执行过程的整合解读

来源:互联网 发布:孙志刚事件网络舆论 编辑:程序博客网 时间:2024/03/28 20:06

解释型语言和编译型语言

有编译无解析: 编译型语言在程序执行之前,先会通过编译器对程序执行一个编译的过程,把程序转变成机器语言。运行时就不需要解析,而直接执行就可以了。最典型的例子就是C语言。

无编译有解析: 解释型语言就没有这个编译的过程,而是在程序运行的时候,通过解释器对程序逐行作出解释,然后直接运行,最典型的例子是Ruby。

先编译后解析: 随着Java等基于虚拟机的语言的兴起,我们又不能把语言纯粹地分成解释型和编译型这两种。用Java来举例,Java首先是通过编译器编译成字节码文件,然后在运行时通过解释器给解释成机器文件。所以我们说Java是一种先编译后解释的语言。Python虽然隐藏得比较深,但其是先编译后解析语言。

Python程序执行过程

与java类似,Python将.py编译为字节码,然后通过虚拟机执行。编译过程与虚拟机执行过程均在python25.dll中。Python虚拟机比java更抽象,离底层更远。

编译过程不仅生成字节码,还要包含常量、变量、占用栈的空间等,Pyton中编译过程生成code对象PyCodeObject。将PyCodeObject写入二进制文件,即.pyc。

pyc文件其实是PyCodeObject的一种持久化保存方式

这里写图片描述

有必要则写入A.pyc指的是该.py是否只运行一次,如果import的模块,肯定会生成.pyc。

Pyc的目的

pyc的目的是重用

pyc文件作为PyCodeObject的一种持久化保存方式的存在,其最大的优点在于我们在运行程序时,不需要重进行重新的编译,直接把pyc文件载入内存,进入解析过程,这样就有点像Ruby那种方式。

什么情况下应该生成Pyc文件呢?

我们需要持久化成pyc文件的应该是那些可以重用的模块。Python的解释器认为:只有被import进来的模块,才是需要被重用的模块。如import requests,则应有持久化文件requests.pyc

为什么只有被import进来的模块,才是需要被重用呢?

我的第一个Python程序helloworld.py不是也需要运行么,虽然不是一个模块(没有人import它),但是以后我每次运行也可以节省时间啊!

我们从实际情况出发,思考下我们在什么时候才可能运行python xxx.py文件:
A. 执行测试时。
B. 开启一个Web进程时。
C. 执行一个程序脚本。

第一种情况我们就不用多说了,这个时候哪怕所有的文件都没有pyc文件都是无所谓的。

第二种情况,我们试想一个webpy的程序把,我们通常这样执行:
这里写图片描述
抑或者:
这里写图片描述
然后这个程序就类似于一个守护进程一样一直监视着8181/9002端口,而一旦中断,只可能是程序被杀死,或者其他的意外情况,那么你需要恢复要做的是把整个的Web服务重启。那么既然一直监视着,把PyCodeObject一直放在内存中就足够了,完全没必要持久化到硬盘上。

第三种情况,执行一个程序脚本,一个程序的主入口其实很类似于Web程序中的Controller,也就是说,他负责的应该是Model之间的调度,而不包含任何的主逻辑在内,如我在http://www.cnblogs.com/kym/archive/2010/07/19/1780407.html中所提到,Controller应该就是一个Facade,无任何的细节逻辑,只是把参数转来转去而已,那么如果做算法的同学可以知道,在一段算法脚本中,最容易改变的就是算法的各个参数,那么这个时候给持久化成pyc文件就未免有些画蛇添足了。

所以我们可以这样理解Python解释器的意图,Python解释器只把我们可能重用到的模块持久化成pyc文件。

Pyc的过期时间

说完了pyc文件,可能有人会想到,每次Python的解释器都把模块给持久化成了pyc文件,那么当我的模块发生了改变的时候,是不是都要手动地把以前的pyc文件remove掉呢?

其实每次在载入之前都会先检查一下py文件和pyc文件保存的最后修改日期,如果不一致则重新生成一份pyc文件。

原创粉丝点击