什么是Python字节码文件
Python是一种解释性语言,在Python执行py脚本文件时,Python解释器将源码转换为字节码写入到内存,然后再由解释器来执行这些字节码。
而在使用import导入其他模块时,则会在模块的py文件旁边自动生成.pyc格式的同名文件,这就是该模块经过编译后生成的二进制字节码文件,优点是加载速度有所提升、实现源码隐藏、一定程度上防止反编译。
每次在导入该模块时,会自动检查其字节码文件的修改时间是否与自身一致,如果一致则直接从该字节码文件读取内容,否则该模块重新导入,并更新当前已有的字节码文件,这样修改模块源代码后,实际使用时也会自动更新。
除了import以外,也可以通过py_compile这个Python自带模块,实现批量生成.pyc文件。
import py_compile py_compile.compile(r"/path/to/pyfile or pydir")
生成错误
最近在维护一份Python2.7版本的代码时,发现一直平稳运行的生产环境报错导入第三方模块错误import error,经过检查发现部分自动生成的.pyc字节码文件大小只有100+字节,正常情况下应该是略大于原始.py文件大小。
在删除该.pyc文件重新运行后,自动生成的新.pyc文件正常,生产环境得以平稳运行。
在搜寻资料后得知,在Python通过import导入py文件时,如果遇到I/O异常,会得到一个EOF标志,然后以所读取到的内容生成pyc文件,但这个过程并没有检查I/O异常。
在模块同时访问量太多、服务器资源紧张、带宽跑满等情况下会比较容易出现这个问题,而在Python3.X版本中修复了此bug,因此在Python2.X中需要多注意一点。
解决方法是通过以下几种方法禁止生成.pyc字节码文件,虽然加载速度会稍受影响,但考虑到稳定性是可以接受的。
设置环境变量
这个方法是较为常用的,也比较方便。
export PYTHONDONTWRITEBYTECODE=1
使用-B参数
在运行py脚本时加上-B参数
python -B test.py
使用dont_write_bytecode函数
在导入模块前写入以下代码
import sys sys.dont_write_bytecode = True
反编译
前面说过pyc字节码文件只能一定程度上防反编译,其实只能防一下小白,通过uncompyle6这个第三方库就可以把pyc字节码文件完美反编译成py源文件,连注释都能保留。
首先安装uncompyle6。
pip install uncompyle6
然后在CMD窗口中运行以下命令
uncompyle6 -o test.py test.pyc
这样就可以将test.pyc字节码文件反编译成test.py源码文件了,如果报错找不到uncompyle6,就把python安装目录下的Scripts文件夹路径添加到系统的PATH环境变量里。
乞丐不会妒忌百万富翁,
但他肯定会妒忌收入更高的乞丐。
——罗素
评论
826509 749260Its difficult to acquire knowledgeable individuals about this topic, and you sound like what happens you are speaking about! Thanks 845670
661269 234348Your talent is actually appreciated!! Thank you. You saved me plenty of frustration. I switched from Joomla to Drupal to the WordPress platform and Ive fully embraced WordPress. Its so much easier and easier to tweak. Anyway, thanks once again. Awesome domain! 80614
183684 52730Some genuinely nice and utilitarian info on this internet website , likewise I think the layout has fantastic capabilities. 288314