Python Pdb 源码解析

本文深入解析Python标准库pdb模块的源码,介绍如何利用cmd和bdb模块实现交互式调试器。核心原理是通过sys.settrace进行代码跟踪,结合cmd模块的交互控制,实现断点、单步执行等功能。文章详细阐述了pdb的启动流程、中断控制逻辑,以及关键调试命令如'step', 'next', 'continue'等的实现原理。" 85242541,8169811,SparkSQL与Hive整合实战,"['Spark', '大数据开发', 'Hadoop', 'Hive', '数据库']
摘要由CSDN通过智能技术生成

 

经常使用Python的同学一定熟悉pdb模块,它是Python官方标准库提供的交互式代码调试器,和任何一门语言提供的调试能力一样,pdb提供了源代码行级别的设置断点、单步执行等常规调试能力,是Python开发的一个很重要的工具模块。

pdb使用方法见官方文档,本文重点分析官方pdb模块源码,介绍调试功能的实现原理。

原理

从cPython源码中可以看到,pdb模块并非c实现的内置模块,而是纯Python实现和封装的模块。核心文件是 pdb.py,它继承自bdb和cmd模块:

class Pdb(bdb.Bdbcmd.Cmd):     ... 

基本原理:利用cmd模块定义和实现一系列的调试命令的交互式输入,基于sys.settrace插桩跟踪代码运行的栈帧,针对不同的调试命令控制代码的运行和断点状态,并向控制台输出对应的信息。

cmd模块主要是提供一个控制台的命令交互能力,通过raw_input/readline这些阻塞的方法实现输入等待,然后将命令交给子类处理决定是否继续循环输入下去,就和他主要的方法名runloop一样。


cmd是一个常用的模块,并非为pdb专门设计的,pdb使用了cmd的框架从而实现了交互式自定义调试。

bdb提供了调试的核心框架,依赖sys.settrace进行代码的单步运行跟踪,然后分发对应的事件(call/line/return/exception)交给子类(pdb)处理。bdb的核心逻辑在对于调试命令的中断控制,比如输入一个单步运行的"s"命令,决定是否需要继续跟踪运行还是中断等待交互输入,中断到哪一帧等。

基本流程

  • pdb启动,当前frame绑定跟踪函数trace_dispatch

def trace_dispatch ( self , frame, event, arg) :

如果自我.退出:

返回 # 无

如果事件 == '行' :

返回自.dispatch_line(帧)

如果事件 == '调用' :

返回自.dispatch_call(帧,arg)

如果事件 == '返回' :

返回自.dispatch_return(帧,参数)

如果事件 == '异常' :

...

  • 每一帧的不同事件的处理都会经过中断控制逻辑,主要是stop_here(line事件还会经过break_here)函数,处理后决定代码是否中断,需要中断到哪一行。

  • 如需要中断,触发子类方法user_#event,子类通过interaction实现栈帧信息更新,并在控制台打印对应的信息,然后执行cmdloop让控制台处于等待交互输入。

def interaction ( self , frame, traceback) :

self .setup(frame, traceback) # 当前栈、frame、local vars

self .print_stack_entry( self .stack[ self .curindex])

self .cmdloop()

self .forget()

  • 用户输入调试命令如"next"并回车,首先会调用set_#命令,对stopframe、returnframe、stoplineno进行设置,它会影响中断控制'''stop_here''的逻辑,从而决定运行到下一帧的中断结果。

def _set_stopinfo ( self , stopframe, returnframe, stoplineno= 0 ) :

自.stopframe = stopframe

self .returnframe = returnframe

self .quitting =  0

# stoplineno >= 0 表示: 停在>线 = stoplineno

# stoplineno -1 的意思是:根本不停止

self .stoplineno = stoplineno

对于调试过程控制类的命令,一般do_#命令都会返回1,这样本次runloop立马结束,下次运行到某一帧触发中断会再次启动runloop(见第三点);对于信息获取类的命令,do_#命令都没有返回值,保持当前的中断状态。

  • 代码运行到下一帧,重复第三点。

中断控制

中断控制也就是对于不同的调试命令输入后,能让代码执行到正确的位置停止,等待用户输入,比如输入"s"控制台就应该在下一个运行frame的代码处停止,而输出"c"就需要运行到下一个打断点的地方。

中断控制发生在sys.settrace的每一步跟踪的中,是调试运行的核心逻辑。

pdb中主要跟踪了frame的四个事件:

  • line:同一个frame中的顺序执行事件

  • call:发生函数调用,跳到下一级的frame中,在函数第一行产生call事件

  • return:函数执行完最后一行(line),发生结果返回,即将跳出当前frame回到上一级frame,在函数最后一行产生return事件

  • exception:函数执行中发生异常,在异常行产生exception事件,然后在该行返回(return事件),接下来一级一级向上在frame中产生exception和return事件,直到回到底层frame。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值