首页
社区
课程
招聘
[原创]Python源码解析-PYC文件
发表于: 2023-3-15 20:54 5962

[原创]Python源码解析-PYC文件

2023-3-15 20:54
5962

PyCodeObject结构

网上有很多关于Pyc文件的介绍。Pyc实际上就是PyCodeObject结构的文件版。不同的的Python版本,其PyCodeObject结构可能会有所不同。就以当前版Python3.11,来说,其结构和Python3.9就有所差别。

 

不同版本的PyCodeObject结构差别无需过多讨论。该结构的定义在Include\cpython\code.h文件中定义。并且相关注释标注清楚完善,无需过多说明。

2.Pyc加载过程

直接运行Pyc

Python在命令行运行文件的时候,会进入到pymain_run_file函数中。该函数主要内容是调用pymain_run_file_obj函数。

 

文本 描述已自动生成

 

pymain_run_file_obj函数主要调用_PyRun_AnyFileObject函数。

 

手机屏幕的截图 描述已自动生成

 

_PyRun_AnyFileObject主要调用_PyRun_SimpleFileObject函数。

 

 

_PyRun_SimpleFileObject函数会通过maybe_pyc_file函数来判断该文件是否是Pyc文件。

 

文本 描述已自动生成

 

判断成功后会去通过run_pyc_file函数来执行该Pyc文件。

 

文本 描述已自动生成

 

之后就是判断文件的头部,magic是否符合版本要求。

 

文本 描述已自动生成

 

通过PyMarshal_ReadLastObjectFromFile函数读取Pyc文件,生成PyCodeObject对象。

 

文本 描述已自动生成

 

随后run_eval_code_obj执行此PyCodeObject对象。

 

文本 描述已自动生成

 

这就是直接运行Pyc时,Pyc文件的加载过程。

通过导入Pyc文件方式执行

Pyc无法直接import导入,可以通过importlib模块进行导入。

 

from importlib.machinery import SourcelessFileLoader

 

hello = SourcelessFileLoader("hello",
"pycache\\hello.cpython-311.pyc").load_module()

 

类SourcelessFileLoader继承于FileLoader和_LoaderBasics。通过其成员函数load_module读取文件生成moudle对象。

 

 

之后通过marshal_loads将moudle对象加载。

 

文本 描述已自动生成

3.认识Python的Opcode

Python的Opcode在Include\opcode.h。

 

关于Opcode的含义,可在https://docs.python.org/3.11/library/dis.html中找到。

 

Opcode的处理在Include\
ceval.c中的_PyEval_EvalFrameDefault。可以看到switch分支处理各个Opcode。

 

文本 描述已自动生成

4.基于PyCodeObject编程

动态修改Python代码。

首先准备一个函数。

 

图形用户界面 低可信度描述已自动生成

 

通过dir函数,我们可以看到函数fun的所有属性。其中fun.code就是函数fun的PyCodeObject对象。函数fun的代码就记录在此。首先要注意的PyCodeObject所处的内存空间是只读属性,所以无法直接对PyCodeObject的成员属性进行修改。

 

 

留意可以发现,其有一个replace的函数。但该函数并不能直接修改原始PyCodeObject对象。调用该函数时,会返回一个新的PyCodeObject。

 

在一个新的py文件中,创建一个新函数new_fun。通过replace,生成一个新的PyCodeObject对象a。将之前fun函数的数据都存入a中。

 

文本 描述已自动生成

 

替换new_fun的code对象。执行函数new_fun,可以发现执行了之前的fun函数。注意:code类型需要转化成function类型才可执行。

 

日程表 低可信度描述已自动生成

 

基于此,可以实现动态修改函数代码的目的。注意,这类方法只适用于function对象的函数。在Py脚本执行时,PyCodeObject各个成员的数据都处在只读内存中,如果想要修改其内容,只能先修改内存属性。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//