当前位置: 首页 > 科技观察

内核级Python:调试Python编译器的源代码

时间:2023-03-14 19:48:27 科技观察

在执行python编译器时,指定要执行的源代码文件,或者直接输入源代码字符串来驱动脚本的执行过程。基本框架如下:输入层是python编译器用来获取源码的输入法。实际上,Python可以通过多种方式将源代码信息传递给编译器,例如:1.执行python-c,然后跟随python代码字符串。2、python-m后跟要执行的模块名3、python后跟脚本文件的路径4、通过管道连接执行,如cat[file]|pythonPython解释器并不关心代码是如何输入的,只要能获取到源代码内容就足够了,所以它专门设置了一个输入层来处理源代码的读取。一旦获取到源代码内容,解释器需要做三个动作。首先是设置编译选项。如果你使用过g++、gcc等编译器,你一定知道在执行过程中有很多设置开关或选项。配置模块负责设置这些选项,State用于存储脚本中设置的各种变量,Module解释脚本后生成便于脚本执行的数据结构。下面我们将描述一些代码和数据结构,这些我们大概知道,不需要掌握或完全理解。我们先看一下解释器在运行脚本之前进行相关配置的代码。相关代码在python目录下的initconfig.h和initconfig.c中。打开initconfig.c,然后搜索PyPreConfig结构体对象,然后按住ctrl点击打开它的定义,一些字段需要注意:1、intallocator,这个字段对应内存分配器类型,它其实是一个枚举值,用于选择不同的内存分配器。2、intisolatd,设置隔离模式,应该对应python虚拟执行环境,其中pip安装或环境变量配置不会影响全局环境。3、intutf8_mode,设置utf-8模式在initconfig.c中搜索PyConfig,这个结构体用于运行时配置,比如设置解释器在执行脚本时是调试模式还是优化模式,它还记录了一些与运行时相关的环境变量配置。接下来,我们在解释器的源代码中设置断点来调试它的执行。操作如下图所示:首先在python模块上右击,选择属性,点击调试,输入python-v-c"p??rint('helloworld')",然后在函数中设置断点config_parse_cmdline,应该在1875行。这个函数用来解释执行python解释器时的命令行参数。设置好后,点击F5开始调试,我们会看到VS在设置断点的地方停止,然后点击F10单步,我们可以看一下函数前几个变量的内容:从中我们可以看到Python解释器对应的可执行文件是python_d.exe,继续往下看代码进入了case'v',这里开启了verbose模式,这样执行的时候会打印出很多信息Python解释器被执行。接下来,在main.c中的pymain_run_command函数中设置断点。这个函数会调用一系列的函数来执行源代码。该文件位于模块目录中。里面的PyRunSimpleStringFlags函数的作用就是执行源码。我们一步步运行函数,然后打开控制台就会看到hello的输出。上面代码中函数PyRunSimpleStringFlags的作用是创建一个Module对象,一个Module对象就是一个可执行的模块,有一个__main入口。