迷途小书童的 Note
读完需要
5
分钟速读仅需 2 分钟
大家好,我是迷途小书童!
今天给大家介绍一个神奇的文件 -- pyc 文件,它能加速 Python 程序的执行速度,同时也能起到保护源码的作用。
1
什么是 pyc 文件?
pyc 文件是经过编译的 Python 字节码文件,其中的 c 是 compiled 的缩写。当我们执行一个 python 源文件时,Python 解释器会先将 python 文件编译成 pyc 文件,然后再执行 pyc 文件。
pyc 文件和 py 文件是一一对应的,文件名相同,只是扩展名不同。pyc 文件无法直接读取,需要反汇编后才能查看内容。
2
解释型语言和编译型语言
计算机是不能够识别高级语言的,所以当我们运行一个高级语言编写的程序的时候,就需要将高级语言翻译成计算机能读懂的机器语言。这个过程分成两类,第一种是编译,另一种是解释。编译型语言在程序执行之前,会先通过编译器对程序执行一个编译的过程,把程序转变成机器语言,运行的时候就不需要翻译,而直接执行就可以了,C 语言就是最典型的编译型语言。解释型语言就没有这个编译的过程,而是在程序运行的时候,通过解释器对程序逐行作出解释,然后直接运行,最典型的例子是 Ruby。由此可见,在运行效率上,解释型语言是无法跟编译型语言相比的。
那问题来了,python 到底是解释型语言还是编译型语言?
python 是编译型 + 解释型的语言,执行的时候是由 python 解释器,逐行编译和解释,然后运行,所以 python 的运行性能会低于编译型语言。为了提高性能,python 解释器,会将模块(往往是需要复用的代码)的编译 + 解释的结果,保存在 pyc 中。这样下次执行的时候,就省了编译这个环节,提高了性能。一次性的脚本文件(比如只有 test.py 且不调用 module 模块),解释器默认是不会保存编译 + 解释的结果,也就是没有 pyc 文件。
3
示例
这里准备 2 个文件,被调用模块 module.py,内容是
def add(x, y):
return x + y
在 test.py 文件中调用 module 中的 add 方法并打印输出
from module import add
a = 2
b = 4
c = add(a, b)
print(c)
然后打开终端 powershell,执行 python test.py,在同一级目录下会生成文件夹 __pycache__,在 __pycache__ 目录下还有一个文件 module.cpython-37.pyc,它是一个二进制文件
通过使用在线 pyc 反编译工具 https://tool.lu/pyc/ ( https://tool.lu/pyc/ ) 知道,module.cpython-37.pyc 就是模块 module.py 编译后的内容
接下来,我们修改下 module.py,加句注释
# add comment
def add(x, y):
return x + y
然后再次执行 python test.py,我们会发现 __pycache__下的module.cpython-37.pyc 也被修改了
我们进入到 __pycache__,将 module.cpython-37.pyc 重命名为 model.pyc,然后将上层目录中的 test.py 拷贝过来,接着执行 python test.py
可以看到,我们可以直接在 python 源码中直接使用 pyc 文件,而不需要 module.py 了,这有点像 c 语言中动态库或静态库,pyc 的这种用法通常用来保护源码。
前面我们讲过解释器默认不支持单文件生成 pyc,如果想生成,需要设定参数处理
python -m py_compile test.py
生成了 __pycache__,我们进入文件夹,可以直接执行 pyc
python test.cpython-37.pyc
4
免费社群