PDB Introduction
PDB Introduction
对于 Python 等宽松的动态类型语言来说,其面对日益膨胀的代码库会变得非常难以维护,因此,有必要使用 Python 原生支持的 pdb debugger 工具来代替 print 大法,实现更加精准并且高效的 Debugging.
Official Docs: pdb official docs
How to set a breakpoint
1 | |
or
1 | |
After setting a breakpoint
在设置断点成功后,程序进入阻塞状态,等待用户命令行的输入:
help
1 | |
控制流跳转操作
next:跳转到下一行但是不进入函数内部step:进入函数执行continue:跳转到下一个断点until: 跳出循环
查看关键信息
where: 打印完整的函数调用链list: 展示源代码的上下文print: 打印变量的值whatis: 打印变量名的类型pp:美化打印
一些组合技:
pp locals(): 打印全部的局部变量pp globals(): 打印全部的全局变量pp {**globals(), **locals()}pp dirs(): 打印全部的变量 (一个包含所有局部变量变量名的列表)pp vars(obj_name): 查看对象的属性字典pp dir(obj_name): 查看对象支持的所有方法和属性
interact
开启一个临时的 Python Session,进行交互式 Python 输入。
pdb 的原理
Creating my own debugger!
1 | |
简单来说,pdb 本质上是一个利用 Python 运行机制来监控自身的 Python 程序。Python 解释器提供了一个名为 sys.settrace() 的函数。pdb 启动过程中会调用该函数并注册一个 Trace Function, 这个 Trace Function 通常会接受 frame: FrameType, event: str, arg: Any 三个参数作为输入值:
- frame:
1
2
3
4
5print(f"Current Code: {frame.f_code}")
print(f"Current Line: {frame.f_lineno}")
print(f"Local variables: {frame.f_locals}")
print(f"Global variables: {frame.f_globals}")
print(f"Reference to the last frame: {frame.f_back}") - event:
1
2
3
4
5
6
7
8
9
10
11if event == "call":
print("Current Event is calling")
elif event == "line":
print("Executing Current Lines")
elif event == "return":
print("The function is returning")
elif event == "exception":
print("Oh! Exception caught") - arg:
- 一些附加的数据
上文实现了一个非常简单的 mini_debugger,这个 debugger 不会处理用户 IO,而是直接在每一行调用时输出一些辅助信息(例如运行代码行数、运行栈帧等等)。而 pdb 的冻结功能可以实现当运行到断点时自动触发跟踪函数,启动用户输入的 while 循环,并在特定命令输入下返回特定的调试信息。
PDB Introduction
https://xiyuanyang-code.github.io/posts/PDB-Introduction/