python字节码
python编译过程
在日常生活中,Python代码一般是不编译的,几个py文件复制来就能用。再加上脚本语言的名头,有些不太了解Python的朋友就以为Python没有编译这个过程。
其实,虽然Python是脚本语言,但它与Java和C#一样,只能执行字节码。
只是Python将编译过程隐藏起来,不大明显而已。
这一章就详细记述一下Python的编译过程以及一些技巧。
这里使用的python版本是3.6.6
py文件
py文件 就是python代码文件
这里准备两个py文件为下面分析使用
mymodule.py
class MyModule(object):
def say(self, name):
print("Say...", name)
demo.py
from mymodule import MyModule
test = MyModule()
test.say("Hello")
运行demo.py方法在当前目录会产生一个__pycache__目录
进入这个目录我们看到里面有个文件mymodule.cpython-36.pyc
这里就有两个问题了
__pycache__目录是什么?
pyc文件又是什么?
__pycache__
__pycache__是包含编译并准备执行Python 3字节码的目录
当第一次运行 python 脚本时,解释器会将 *.py 脚本进行编译并保存到 __pycache__ 目录
这里有个问题?
我就写个一个文件,里面就打印一句话,会不会产生pycache目录呢?
print("hello world")
实验表明:
并不会产生这个pycache目录,这个目录只有当import xxx才会生成
这个目录能不能删掉呢?删掉有什么影响呢?
下次执行脚本时,若解释器发现你的 .py 脚本没有变更,便会跳过编译一步,直接运行保存在 __pycache__目录下的.pyc 文件
执行python脚本会导致字节代码在内存中生成并保持到程序关闭。
如果导入模块,为了更快的可重用性,Python将创建一个缓存.pyc(PYC是'Python''Compiled')文件,其中导入的模块的字节代码被缓存。
想法是通过避免在重新导入时重新编译(编译一次,运行多次策略)来加速python模块的加载。
文件名与模块名称相同。
初始点后面的部分表示创建缓存的Python实现(可能是CPython),后跟其版本号。
如前面说的mymodule.cpython-36.pyc文件
pyc文件
python2 代码 运行是直接在本地产生pyc文件
python3 代码运行是把pyc文件放在pycache目录
.pyc文件是由.py文件经过编译后生成的字节码文件,其加载速度相对于之前的.py文件有所提高,而且还可以实现源码隐藏,以及一定程度上的反编译
pyc文件,是python编译后的字节码(bytecode)文件。
只要你运行了py文件,python编译器就会自动生成一个对应的pyc字节码文件。
这个pyc字节码文件,经过python解释器,会生成机器码运行
下次调用直接调用pyc,而不调用py文件。直到你这个py文件有改变。
python解释器会检查pyc文件中的生成时间,对比py文件的修改时间,如果py更新,那么就生成新的pyc。
pyo文件
pyo文件也是优化(注意这两个字,便于后续的理解)编译后的程序(相比于.pyc文件更小),也可以提高加载速度。
但对于嵌入式系统,它可将所需模块编译成.pyo文件以减少容量。 但总的来说,作用上是几乎与原来的.py脚本没有区别的,
在所有的Python选项中:
-O,表示优化生成.pyo字节码
-OO,表示进一步移除-O选项生成的字节码文件中的文档字符串
-m,表示导入并运行指定的模块
执行下面的命令查看是否生成pyo文件
#py_compile是Python的自带模块
python -O -m py_compile demo.py
python -OO -m py_compile demo.py
到pycache目录看到生成了cpython-36.opt-1.pyc文件
我们发现下面的结果:
1.咦,说好的生成pyo文件的呢?怎么又生成了pyc文件?
2.两个pyc文件
-O 选择生成的是xxxx-1.pyc
-OO 选项生成的是xxxx-2.pyc
这两个pyc又有啥区别呢?
查资料,发现从python3.5+开始就去除了pyo文件后缀名,
消除pyo文件原文链接
PYC目录链接
为啥官方要去除pyo呢?
我读完这两篇文章,简单总结下:
由于pyc 文件在 Python 主要版本之间并不兼容
所以引入了一种更灵活的替代机制 -pyc
格式包含实现名称和版本号
*.pyc 文件可以表示优化和未优化的字节码。
优化级别信息可以包含在 *.pyc 文件的名字中,
优化级别:
0: .pyc
1 (-O): .pyo
2 (-OO): .pyo
python程序执行原理