一、什么是pyc文件
pyc文件是py文件编译后生成的字节码文件(byte code)。pyc文件经过python解释器最终会生成机器码运行。所以pyc文件是可以跨平台部署的,类似Java的.class文件。一般py文件改变后,都会重新生成pyc文件
pyc文件生成
import py_compile
py_compile.compile("1.py")
二、pyc文件详解
1、Python 是一种解释型、面向对象、动态数据类型的高级程序设计语言。;
2、Python是解释型语言,没有严格意义上的编译和汇编过程。但是一般编写好的.py源文件,由python解释器翻译成以.pyc为结尾的字节码文件,该文件可由python虚拟机直接运行;
3、根据python源码中提供的opcode,可以根据pyc文件反编译出py文件源码;
4、加载模块时,如果同时存在.py和.pyc,Python会尝试使用.pyc,如果.pyc的编译时间早于.py的修改时间,则重新编译.py并更新.pyc;
5、python的pyc文件,python2与python3头有所不同,python2有8字节的头,而python3有16字节的头,主要是魔术字(python版本)和时间属性的二进制信息
PyCodeObject结构
Python代码的编译结果就是PyCodeObject对象。PyCodeObject对象可以由虚拟机加载后直接运行,而pyc文件就是PyCodeObject对象在硬盘上的保存形式。
PyCodeObject对象一般包含的属性名称及数据类型如下,每个属性在虚拟机执行pyc文件时都有其作用。
typedef struct {
PyObject_HEAD
int co_argcount; /* 位置参数个数 */
int co_nlocals; /* 局部变量个数 */
int co_stacksize; /* 栈大小 */
int co_flags;
PyObject *co_code; /* 字节码指令序列 */
PyObject *co_consts; /* 所有常量集合 */
PyObject *co_names; /* 所有符号名称集合 */
PyObject *co_varnames; /* 局部变量名称集合 */
PyObject *co_freevars; /* 闭包用的的变量名集合 */
PyObject *co_cellvars; /* 内部嵌套函数引用的变量名集合 */
/* The rest doesn’t count for hash/cmp */
PyObject *co_filename; /* 代码所在文件名 */
PyObject *co_name; /* 模块名|函数名|类名 */
int co_firstlineno; /* 代码块在文件中的起始行号 */
PyObject *co_lnotab; /* 字节码指令和行号的对应关系 */
void *co_zombieframe; /* for optimization only (see frameobject.c) */
} PyCodeObject;
python中使用marshal.dump的方法将PyCodeObject对象转化为对应的二进制文件结构。PyCodeObject对象中的每一个属性及值都会按照一定的顺序表示在二进制文件里。
PyCodeObject每个字段在二进制文件中的结构如图1:
PyCodeObject每个字段在二进制文件中的结构
byte表示占用1个字节,long表示占用4个字节,bytes表示该字段可能占用1到多个字节。
pyc文件结构主要包括两部分:pyc文件头部表示和PyCodeObject对象部分。上述即PyCodeObject对象的二进制部分,pyc文件头部较简单,在python2中只占用4个字节包含两个字段magic和mtime,完整的pyc文件结构见图2:
完整的pyc文件结构
三、pyc转py
方法一:
uncompyle6 -o test.py test.pyc
方法二:
https://tool.lu/pyc/