PyCodeObject。
pyc文件的读入:
读入pyc文件的部分可以参考python的importlib。在3.6版本中,读入pyc文件的逻辑在importlib/_bbotstrap_external.py中。pyc文件中除了存储codeobject之外,还存储了头部信息。
对头部信息的判断在_validate_bytecode_header中:
magic = data[:4]
raw_timestamp = data[4:8]
raw_size = data[8:12]
前四字节为Magic Number,用来对pyc文件的版本进行校验。_validate_bytecode_header在SourceLoader类的get_code中被调用。get_code中先使用_validate_bytecode_header检查头部,之后使用_compile_bytecode处理,而_compile_bytecode中则是调用了marshal.loads。marshal实现的是对象的序列化和反序列化操作,marshal.load是将一个序列化的对象读取到内存中。
参照这一过程,可以如下实现读取pyc文件的功能:
def read_pyc(pyc_filename):
fp = open(pyc_filename, "rb")
magic = fp.read(4)
raw_timestamp = fp.read(4)
raw_size = fp.read(4)
c = marshal.load(fp)
return c
这一函数忽略了检查过程,跳过文件头部之后读取codeobject。读取到codeobject之后,可以用dir函数查看其属性,之后读取对应属性并输出。
其他部分,3中与2中差别不大。3中的codeobject的属性与书中一致,dis模块也依然在。用于序列化和反序列化的marshal模块实现因为不是一个关键因素,就未与书中进行对比了。