## Python细说pyc
### 1. Python是一门解释型语言?
相信听说过或在学python的同学都听说过“Python是一门解释性语言”,如果细心的同学,应该会留意到*.pyc的文件,这个文件是什么时候生成的,它究竟有什么作用呢?
今天就来帮大家解解疑惑,如果大家对解释型语言和编译型语言不太明白的,建议先看看《编程基础——解释型语言和编译型语言》
### 2. 执行“python a.py”时发生了什么
当我们在命令行输入```python a.py```时,实际上是激活了Python的解释器,然而在真正运行代码前,它还是需要对代码进行一次解释过程。
### 3. 什么情况下会生成pyc
#### 环境说明
* Python版本:3.6
* Centos 7
#### print_hello.py
print("I am "+__name__)
print('hello')
#### import_hello.py
import print_hello
#### 直接运行脚本:不生成
[root@teach tmp]# python print_hello.py
I am __main__
hello
[root@teach tmp]# ls
import_hello.py print_hello.py
#### 模块导入:生成
[root@teach tmp]# python import_hello.py
I am print_hello
hello
[root@teach tmp]# ls
import_hello.py print_hello.py print_hello.pyc
#### 注意
* 在windows下,python3下pyc文件是生成在当前目录下的__pycache__目录
* 有兴趣的同学可以自己测试一下
### 4. pyc设计的目的
通过测试发现,pyc文件只有在文件被当成模块导入时才会生成。也就是说,Python解释器认为,只有import进行的模块才需要被重用。
生成pyc文件的好处显而易见,当我们多次运行程序时,不需要重新对该模块进行重新的解释。
如果我的需要直接执行的print_hello.py文件也需要重复生成pyc文件怎么办呢?python提供了方法。
### 5. pyc的过期时间
* Python解释器会把模块持久化成了pyc文件,那么当模块发生了改变的时候怎么办?需要手动删除吗?
* 可以通过查看源码得到以下结论
* 在写入pyc文件的时候,写了一个Long型变量,变量的内容则是文件的最近修改日期
* 每次在载入之前都会先检查一下py文件和pyc文件保存的最后修改日期,如果不一致则重新生成一份pyc文件
### 6. Python运行过程
#### PyCodeObject与pyc文件
* PyCodeObject则是Python编译器真正编译成的结果,存放到内存
* pyc文件其实是PyCodeObject的一种持久化保存方式
#### 直接执行
* Python解释器会对脚本进行一次解释,将结果保存在内存中的PyCodeObject中
* 程序运行
#### import导入
* 当Python程序被导入时,会先在硬盘中寻找pyc文件
* 若找到pyc文件,并确认文件为最新,则直接使用
* 若未找到或py文件做过修改,则先对模块进行解释,并将结果写回到pyc文件中,然后使用
### 一些启示
其实了解Python程序的执行过程对于大部分程序员,包括Python程序员来说意义都是不大的,那么真正有意义的是,我们可以从Python的解释器的做法上学到什么,我认为有这样的几点:
A. 其实Python是否保存成pyc文件和我们在设计缓存系统时是一样的,我们可以仔细想想,到底什么是值得扔在缓存里的,什么是不值得扔在缓存里的。
B. 在跑一个耗时的Python脚本时,我们如何能够稍微压榨一些程序的运行时间,就是将模块从主模块分开。(虽然往往这都不是瓶颈)
C. 在设计一个软件系统时,重用和非重用的东西是不是也应该分开来对待,这是软件设计原则的重要部分。
D. 在设计缓存系统(或者其他系统)时,我们如何来避免程序的过期,其实Python的解释器也为我们提供了一个特别常见而且有效的解决方案。
### 参考
[博客园-飞林沙](http://www.cnblogs.com/kym/archive/2012/05/14/2498728.html)
文章最后更新时间:
2017年08月09日 13:14:50