python高级调试技巧(一)——原生态的pdb调试
目录
一 使用系统自带的pdb模式模块进行单
步调试
二 使用set_trace()设置断点
三 pdb模块方法详解
四 使用ipython和jupyter notebook
进行调试(下篇预告)
声明:本文所讲的调试是指不附带任何工具的调试,我们平时使用vs code,pycharm进行调试,包括设置断点、单步执行、多步执行等操作都是IDE设置好的,本文不考虑这些,使用原生态的python调试器,不需要任何IDE开发环境。pdb是python自带的调试器,是python debugger 的简称。使用pdb调试有两种方式。
本次文章依然是分为系列文章进行讲解,本文为系列文章第一篇。
01
使用系统自带的pdb模式模块进行单
步调试
所谓的单步调试,就是指的是每次执行一句Python语句。 单步执行代码,通过在用户终端命令 python -m pdb xxx.py 启动脚本,进入单步执行模式。注意在终端命令输入的前面,会有这样一个显示:
(Pdb),这就表示进入了pdb命令调试。然后输入下面的命令即可。
注意:我们经常看见在python代码中会有 import pdb 这样的语句,但是这样的“单步执行模式”,是不需要在代码里面添加这句话的,当然添加也可以。
pdb命令行:
1)进入命令行Debug模式,python -m pdb xxx.py 这个格式是固定的
之所以可以这样做,主要是因为pdb.py 可以被当做一个脚本script执行。
2)h:(help)帮助
3)w:(where)打印当前执行堆栈
4)d:(down)执行跳转到在当前堆栈的深一层(个人没觉得有什么用处)
5)u:(up)执行跳转到当前堆栈的上一层
6)b:(break)添加断点
b 列出当前所有断点,和断点执行到统计次数
b line_number:当前脚本的line_no行添加断点
b filename:line_number:脚本filename的line_no行添加断点
b function:在函数function的第一条可执行语句处添加断点
7)tbreak:(temporary break)临时断点
在第一次执行到这个断点之后,就自动删除这个断点,用法和b一样
8)cl:(clear)清除断点
cl 清除所有断点
cl bpnumber1 bpnumber2... 清除断点号为bpnumber1,bpnumber2...的断点
cl line_number 清除当前脚本line_number行的断点
cl filename:line_number 清除脚本filename的line_number行的断点
9)disable:停用断点,参数为bpnumber,和cl的区别是,断点依然存在,只是不启用
10)enable:激活断点,参数为bpnumber(即哪一个断点,1,2,3,4......)
11)s:(step)执行下一条命令
如果本句是函数调用,则s会执行到函数的第一句
12)n:(next)执行下一条语句
如果本句是函数调用,则执行函数,接着执行当前执行语句的下一条。
13)r:(return)执行当前运行函数到结束
14)c:(continue)继续执行,直到遇到下一条断点,这个比较重要,常常和断点结合起来使用。
15)l:(list)列出源码
l 列出当前执行语句周围11条代码
l first 列出first行周围11条代码
l first second 列出first--second范围的代码,如果second 16)a:(args)列出当前执行函数的函数 17)p expression:(print)输出expression的值 比如:(Pdb) p 1+2 这里会打印出 3 再比如:(Pdb) p c #这里用来查看某个变量c的值 18)pp expression:好看一点的p expression 19)run:重新启动debug,相当于restart 20)q:(quit)退出debug 21)j lineno:(jump)设置下条执行的语句函数 只能在堆栈的最底层跳转,向后重新执行,向前可直接执行到行号 22)unt:(until)执行到下一行(跳出循环),或者当前堆栈结束 23)condition bpnumber conditon,给断点设置条件,当参数condition返回True的时候bpnumber断点有效,否则bpnumber断点无效 注意: 1:直接输入Enter,会执行上一条命令; 2:输入PDB不认识的命令,PDB会把他当做Python语句在当前环境下执行; 3:常用的命令有,(6)(8)(9)(10)(11)(12)(13)(14)(15)(16)(17)(18)(19)(20) 02 使用set_trace()设置断点 pdb单步执行太麻烦了,所以第二种方法是import pdb 之后,直接在代码里需要调试的地方放一个pdb.set_trace(),就可以设置一个断点, 程序会在pdb.set_trace()暂停并进入pdb调试环境,可以用pdb 变量名查看变量,或者c继续运行。 如下代码: import pdb #导入这个模块 print('这是一个python调试程序') def func1(): for i in range(5): print(i) def func2(a,b): return a/b if __name__=='__main__': func1() pdb.set_trace() #设置断点,程序会在调试的时候直接进入到这里暂停 result=func2(3,0) print(result) 下面开始调试, (base) C:Userslenovo>python F:Python调试.py #执行脚本 这是一个python调试程序 0 1 2 3 4 #自动执行到断点处 > f:研究生二年级下c#再学习python调试python调试python调试.py(14) -> result=func2(3,0) (Pdb) n ZeroDivisionError: division by zero > f:研究生二年级下c#再学习python调试python调试python调试.py(14) -> result=func2(3,0) (Pdb) n --Return-- > f:研究生二年级下c#再学习python调试python调试python调试.py(14) -> result=func2(3,0) (Pdb) n 总结: 使用set_trace()设置断点之后,调用脚本的时候,不再需要 -m pdb 这一块了,直接调用,然后就会进入调试模式, 几面会出现(Pdb),然后相关的执行命令和前面的是一样的。 03 pdb模块详解 1、pdb.set_trace() 设置断点 2、pdb.run(statement[, globals[, locals]]) ——主要用来调试代码块 statement:需要进行调试的某一段代码,以字符串的形式给出 globals: 设置statement运行的全局环境变量 locals: 设置statement运行的局部环境变量 整体的作用类似于python内置模块的eval函数。 s='''a=100 b=20 c=0 d=a/b e=d/c ''' pdb.run(s) 现在运行上面这段代码,python Python调试.py 的搭配下面的结果: (base) C:Userslenovo>python F:研究生二年级下C#再学习Python调试Python调试Python调试.py > (Pdb) n > (Pdb) n > (Pdb) n > (Pdb) n > (Pdb) n ZeroDivisionError: float division by zero > 补充: (1)globals:这个参数管控的是一个全局的命名空间,也就是我们在计算表达式的时候可以使用全局的命名空间中的函数,如果这个参数被提供了,并且没有提供自定义的__builtins__,那么会将当前环境中的__builtins__拷贝到自己提供的globals里,然后才会进行计算。关于__builtins__,它是python的内建模块,也就是python自带的模块,不需要我们import就可以使用的,例如我们平时使用的int、str、abs等都在这个模块中。关于它的说明可以参照这篇文章:点击打开链接。如果globals没有被提供,则使用python的全局命名空间。 (2)locals:这个参数管控的是一个局部的命名空间,和globals类似,不过当它和globals中有重复的部分时,locals里的定义会覆盖掉globals中的,也就是当globals和locals中有冲突的部分时,locals说了算,它有决定权,以它的为准。如果locals没有被 提供的话,则默认为globals。 3、pdb.runeval(expression,globals,locals)——主要用来调试表达式 expression也是以字符串的形式给出的,当表达式有返回值的时候,这个函数返回的值就是表达式所返回的值,如果没有返回值,那和上面的pdb.run()是一样的。 4、pdb.runcall(function[, argument, ...])——主要用来调试函数 对一个函数进行调试,注意,这里的function是一个函数或者是方法对象,不再是字符串哦,后面的是参数。当韩树有返回值的时候,函数的返回值就是runcall的返回值。 def myfunc(a,b,c): return (a/b)/c result=pdb.runcall(myfunc,100,20,5) print(result) 5、pdb的其他一些方法 除了上面几个常用的常用方法以外,还有以下几个常用方法, pdb.post_mortem([traceback]) pdb.pm() Python学习路线和PDF电子书相互配合学习:获取方式很简单:只需关注转发文章然后私信小编(学习)就行! Python 全系列 第一阶段:Python入门第二阶段:Python 深入与提高第三阶段:Python 网络与并发编程第四阶段:数据库编程基础第五阶段:Linux 环境编程基础第六阶段:Python 核心特性第七阶段:网页编程基础第八阶段:Python_Django 框架第九阶段:Python_Tornado 框架第十阶段:Python_大型电商项目第十一阶段:Python 爬虫开发第十二阶段:面试和成功求职的秘技第十三阶段:入职后快速成长到CTO 获取方式很简单:只需关注转发文章然后添加微信:15803464551 备注:A 就可获取到了!