参考:https://www.zhihu.com/question/30296617
1 什么是pyc
首先了解下python的运行机制及特性:当我们运行python文件程序的时候,Python解释器将源码转换为字节码,然后再由解释器来执行这些字节码,整体执行流程如下:
- 完成模块的加载和链接;
- 将源代码翻译为PyCodeObject对象(字节码),并将其写入内存当中(方便CPU读取,起到加速程序运行的作用);
- 从上述内存空间中读取指令并执行;
- 程序结束后,根据命令行调用情况(即运行程序的方式)决定是否将PyCodeObject写回硬盘当中(也就是直接复制到.pyc或.pyo文件中);
- 之后若再次执行该脚本,则先检查本地是否有上述字节码文件。有则执行,否则重复上述步骤。
因此python具有以下三条特性
- 源码距离底层更远
- 运行时都需要生成字节码,交由解释器执行。
- 每次执行脚本,虚拟机总要多出加载和链接的流程,所以相比于编译型语言就有点慢了。
pyc文件是py文件编译后生成的字节码文件(byte code)。pyc文件经过python解释器最终会生成机器码运行。所以pyc文件是可以跨平台部署的,类似Java的.class文件。所以,在我们运行python文件的时候,就会自动首先查看是否具有.pyc文件,如果有的话,而且.py文件的修改时间和.pyc的修改时间一样,就会读取.pyc文件,否则,Python就会读原来的.py文件。
2 pyc特点
- .pyc文件是由.py文件经过编译后生成的字节码文件,其加载速度相对于之前的.py文件有所提高,而且还可以实现源码隐藏,以及一定程度上的反编译。比如,Python3.3编译生成的.pyc文件,Python3.4就别想着去运行啦!→_→
- .pyo文件也是优化(注意这两个字,便于后续的理解)编译后的程序(相比于.pyc文件更小),也可以提高加载速度。但对于嵌入式系统,它可将所需模块编译成.pyo文件以减少容量。
3 生成pyc的方法
我们可以使用如下格式运行.py文件来生成.pyc文件(以下调用均假设/path/to目录含有.py脚本):
python -m py_compile /path/to/需要生成.pyc的脚本.py
#若批量处理.py文件,则替换为/path/to/{需要生成.pyc的脚本1,脚本2,...}.py
其效果等同于如下代码
import py_compile
py_compile.compile(r'/path/to/需要生成.pyc的脚本.py')
#此处尽可能使用raw字符串,从而避免转义的麻烦。比如,这里不加“r”的话,你就得对斜杠进行转义
生成的pyc在__pycache__
目录下,但是会带版本号,这需要自己去删除,删除原py文件,不用修改源码的import,会自动去调用pyc文件
另外,生成.pyo文件的格式调用如下:
python -O -m py_compile /path/to/需要生成.pyo的脚本.py
注意:-O选项,将.pyc文件优化(注意我一直强调的“优化”二字,这里就用到啦!)为.pyo文件,而不是将.py文件优化编译为.pyo文件。(其直接的结果是优化编译后的文件略微小于.pyc文件,也就是“减肥”了。现在,大家知道.pyo文件为什么小的原因了吧!)
以上无论是生成.pyc还是.pyo文件,都将在当前脚本的目录下生成一个含有字节码的文件夹__pycache__。