1.概述
在Python工作目录下,执行某个文件经常会自动生成一个__pycache__文件夹。这个文件夹到底是什么东西呢?
2. __pycache__文件的产生
假设我们现在有一个两个python文件,分别为test.py与main.py,在同一个文件夹下,main.py会调用test.py中的函数test()函数
# main.py
import test
test.test()
# test.py
def test():
print("test")
- 当只运行test.py文件的时候并不会生成__pycache__文件
- 当运行main.py的时候生成__pycache__文件,在__pycache__文件中有test.cpython-39.pyc文件。cpyhon-39表示python版本为python3.9
- pyc文件的生成主要是为了提高模块的加载速度和重用性。直接运行脚本时通常不会生成pyc文件,因为脚本是一次性执行的,不需要存储编译结果。而导入模块时生成的pyc文件可以确保模块在后续导入时能够快速加载,提高运行效率。
强制生成pyc文件:
以下命令将会编译当前目录下所有python文件,并将生成pyc文件保存在__pycache__目录中
python -m compileall .
2.相关概念
源代码:我们每天编写的python、C++等代码通常指的就是源代码,源代码的特点是人类可读的。但是CPU只能看懂二进制,看不懂我们写的源代码,因此还需要编译。
字节码:因为CPU读不懂源代码,因此需要对原源代码进行编译:把源代码(原始语言)转化成另一种编程语言(目标语言)的过程称为编译。但是在python中并不是把源代码直接翻译为机器码,还需要经历一个中间语言,即字节码,字节码以字节形式存储的
机器码:CPU可直接解读的代码,也成为native code
解释器:在Python中解释器是一种让python程序运行起来的程序,编写的python程序必须在解释器中执行
虚拟机:生成了字节码后,就会被发送到python虚拟机(Python virtual machine, PVM)中执行,因此python虚拟机是python解释器的最后一步
3.python的工作机制
对于一个.py文件,在执行过程中:
- 解释器会先把.py文件编译为字节码,并缓存在*.pyc中
- 编译产生的字节码被python虚拟机逐行执行
4. 为什么要有__pycache__文件
如上文所说,字节码缓存在*.pyc文件中,而__pycache__文件夹正是缓存*.pyc文件的地方。
那么根本问题来了,为什么要这么做呢?为什么要设置一个中间代码呢?这背后的逻辑和JAVA是一样的,主要是为了解决跨平台性。Java的执行过程中也是先把源代码编译成字节码,然后进入java虚拟机执行,java虚拟机会屏蔽掉不同操作系统及CPU之间的差异,因此会解决跨平台问题。
虽然提升了跨平台性,却因为中间码的存在降低了运行速度。Python如何解决这个问题的呢?Python在下一次执行的时候,会检查代码文件(.py)与字节码文件(.pyc)的时间戳,如果时间戳一致,则说明源代码没有被修改,就会跳过对源代码编译过程而直接加载字节码进入虚拟机执行。如果时间戳不一致,才会重新编译。而字节码的执行相对较快,这样就大大缩短了项目前期准备时间。