三步学会 Debug 神器,效率提升不少!

栏目: Python · 发布时间: 6年前

三步学会 Debug 神器,效率提升不少!

三步学会 Debug 神器,效率提升不少!

PDB是 Python 自带的一个包,为Python程序提供了一种交互的源代码调试功能,主要特性包括设置断点、单步调试、进入函数调试、查看当前代码、查看栈片段、动态改变变量的值等。

三步学会 Debug 神器,效率提升不少!

启动调试工具

使用PDB的第一步是让解释器在适当的时候进入调试工具。可以采用很多不同的方法
达到这个目的,具体取决于起始条件和所要调试的内容。

从命令行执行:

PDB的最直接的方式是通过命令行运行,命令格式如下:

python3 -m pdb py文件

这里我们来个小例子,有一个文件名为1.py,代码如下:

def foo(num):     print(f"当前的数字是:{num}") if __name__ == '__main__':     foo(3) 

然后再命令行中定位到当前位置。

三步学会 Debug 神器,效率提升不少!

通过命令行运行PDB

通常PDB在打印一个文件名时会在输出中包含各模块的完整路径,然后会显示出下一行将要运行的代码。这个里的话就是接下来将运行函数foo了。

在解释器中运行:

如果在交互式环境下运行调试工具,可以使用run()或者runeval()。

在程序中运行:

上面的情况只是适合一开始就启动调试工具,对于长时间的而且需要运行一段时间才去进行调试的情况,更方便的做法就是在需要运行的代码之前加set_trace()方法了。
set_trace()可以在任意位置进行调用,像下面的例子。

import pdb def foo(num):     print(f"当前的数字是:{num}")     for i in range(num):         pdb.set_trace()         print(f"当前循环的数字:{i}") if __name__ == '__main__':     foo(10) 

三步学会 Debug 神器,效率提升不少!

上面的代码在for循环中打了一个断点,可以发现我们程序停在了for循环的位置,然后显示出下一行将要执行的内容

print(f"当前循环的数字:{i}") 

怎么知道循环到第几个数字呢?

答:通过直接输入变量i可以看到当前的值。

怎么知道当前的代码运行到哪了?

答:通过命令where(简写w)可以得出正在执行哪一行,以及程序的调用栈的位置。

如何查看附近当然代码附近的代码信息?

答:通过list(简写l)可以看周围的代码默认是上5行、下5行。另外命令longlist(简写ll)可以输出当前的函数的源码。如果需要看整个类的源码可以通过source+类名获取源码。

三步学会 Debug 神器,效率提升不少!
三步学会 Debug 神器,效率提升不少!

三步学会 Debug 神器,效率提升不少!

常用命令

步骤执行:

step(简称s):函数单步执行,如果遇到函数会进入函数内部继续调试,如果不需要进入函数体只是一步一步执行,此时就要用下面的next了。

next(简称n):单步执行命令,不会进入函数体,但是向之前说的那个如果遇到了一个for循环10次还好如果是10000次呢,此时就要用到下面的命令了。

until:该命令类型next,只不过它会继续执行,直到执行到同一个函数中行号大于当前值的一行,也就是说可以用until跳出循环末尾。当然until也可以指定一个比当前行号大的值,调到指定位置。

一个例子:

import pdb class Myobj():     def foo(self,num):         print(f"当前的数字是:{num}")         pdb.set_trace()         for i in range(num):             print(f"当前循环的数字:{i}")         print("over") if __name__ == '__main__':     m=Myobj()     m.foo(4) 

三步学会 Debug 神器,效率提升不少!

可以发现执行until把整个循环走了一遍,然后到下一行也就是。

-> print("over") 

return:return也可以绕开一段代码的捷径,只不过它会继续执行。

直至函数准备执行一个return语句,然后会暂停,使得在函数返回之前可以看到返回值。

一个没什么实际用途的例子,不过可以很好地演示这个效果。

import pdb lst=[] class Myobj():     def foo(self,num):         print(f"当前的数字是:{num}")         pdb.set_trace()         for i in range(num):             print(f"当前循环的数字:{i}")             lst.append(i)         return lst if __name__ == '__main__':     m=Myobj()     m.foo(4) 

三步学会 Debug 神器,效率提升不少!

断点相关:

break(简称b): 当然随着代码的增长即使使用return和until或者next都很费时间,此时就要考虑在指定位置设置断点的方式了,如果要在文件的一个特定行设置断点,可以使用break lineno,然后通过下面的continue(简写c)命令调到下一个断点。

我们还可以指定在某个函数中设置断点比如:break Myobj().foo。

除此之外还可以执行其他文件设置断点,也可以相当于sys.path上将某个文件的相对路径。如果只执行break命令可以看到哪些地方有断点,包括哪个文件行号等信息。

disable:可以指定上面break之后显示的断点,执行后可以发现之前Enb栏有yes变为false。此时输入l可以看到打断点的为会有B标识。

如果想彻底删除就需要执行clear命令了。

三步学会 Debug 神器,效率提升不少!

添加和删除断点效果展示图

clear:彻底删除一个断点,使用方式clear id号,类型disable。

tbreak:临时断点,程序第一次执行到临时断点时会自动清除。不用再去手动删除了。

条件断点:

可以对断点应用一些规则,以便其仅当条件满足时才执行。与手动启用和禁用断点相比,使用条件断点可以更好地控制调试器暂停程序的方式。

条件断点可以通过两种方式设置。第一种方法是指定使用break设置断点时的条件。使用方法是代码行号加表达式。看一个应用例子。

import pdb lst = [] class Myobj():     pdb.set_trace()     def foo(self, num):         print(f"当前的数字是:{num}") if __name__ == '__main__':     m = Myobj()     [m.foo(i) for i in range(10)] 

三步学会 Debug 神器,效率提升不少!

解析下图中命令的含义:

1.break 10,num>5,是指在第10行打断点,然后条件是num>5的时候,通过后面输出break可以看到具体的断点信息,很明显看到我们的断点条件。

stop only if num>5

2.如果表达式的计算结果为true,则执行将在断点处停止。

除此之外,还可以使用条件命令将条件应用于现有断点。参数是断点id和表达式。

还是上面的代码让我们看效果图。

三步学会 Debug 神器,效率提升不少!

忽略断点

如果在循环的过程中想忽略前几条结果,比如这里忽略前3个,就可以使用ignore。

使用方法是:

ignore 断点id 忽略次数。 

如果在运行之前不想忽略了可以使用下面命令,如果已经运行continue了的话就没效果了。

ignore 断点id 0 

三步学会 Debug 神器,效率提升不少!

监视变量:

display:有时候我们需要实时观察一个变量的变化,这个时候dispaly就是最好的帮手,如果想移出可以使用undisplay。

三步学会 Debug 神器,效率提升不少!

display监视变量

改变工作流:

jump:jump命令在运行时改变程序的流程,而不修改代码。 它可以向前跳过以避免运行某些代码,也可以向后跳转以再次运行它。

import pdb def f(n):     pdb.set_trace()     result = []     j = 0     for i in range(n):         j = i * n + j         j += n         result.append(j)     return result if __name__ == '__main__':     print(f(5)) 

向前跳:

向前跳转会将执行点移动到当前位置之后,而不会执行期间任何语句。

三步学会 Debug 神器,效率提升不少!

向后跳:

跳转还可以将程序执行移动到已经执行的语句中,以便再次运行它。

不允许的jump方式

1.跳入和跳出某些流控制语句,无法判断什么时候进入。

2.跳转可以用来输入函数,但是不给参数,代码也不能工作。

3.跳转不会进入for循环或try:except语句等块的中间。

4.finally块中的代码必须全部执行,因此跳转不会离开该块。

5.最基本的限制是跳转被限制在调用堆栈的底部框架上。 向上移动堆栈以检查变量后,此时无法更改执行流程。

三步学会 Debug 神器,效率提升不少!

其他命令

  • up(简称u):可以向栈中较旧的帧移动

  • down(简称d) 可以向栈中较新的帧移动。 每次在栈中上移或者下移时,调试 工具 都会打印当前位置,格式与where生成的格式相同。

  • args(简称a) 可以打印当前函数的所有参数的值。

  • p和pp 这两个是类似python的print和pprint的功能。输出信息的,pp带有美化功能。

  • ! 在一个表达式前面加一个!,可以修改python程序当前正在运行的值,比如上面的例子num等于10,如果执行!num=3,后面再输出num你会看到此时的num变成3了,这个可以减少测试时候我们的循环次数了。当然这个循环次数是否可以变动还是看程序的逻辑。

  • 参考资料

https://docs.python.org/3.7/library/pdb.html

作者简介:陈祥安,高级爬虫工程师,从业多年,有着丰富的爬虫工作经验,从c#语言转入到Python语言,擅长各种爬虫技术,熟悉大规模爬虫开发,热爱并喜欢钻研 P ython。欢迎大家和我一起来交流学习。

本文系作者投稿,版权归作者所有。

【END】

三步学会 Debug 神器,效率提升不少!

作为码一代,想教码二代却无从下手:

听说少儿编程很火,可它有哪些好处呢?

孩子多大开始学习比较好呢?又该如何学习呢?

最新的编程教育政策又有哪些呢?

下面给大家介绍CSDN新成员: 极客宝宝(ID: geek_baby)

戳他了解更多↓↓↓

三步学会 Debug 神器,效率提升不少!

 热 文推 荐 

  手机基带芯片激荡 30 年!

硬核追星!杨超越杯决赛是些啥编程项目?

前端代码的整洁之道 | 技术头条

☞  异构计算=未来?一文带你秒懂3大主流异构

☞ 她说:为啥 程序员 都特想要机械键盘?这答案我服!

System.out.println("点个在看吧!");
console.log("点个在看吧!");
print("点个在看吧!");
printf("点个在看吧!\n");
cout << "点个在看吧!" << endl;
Console.WriteLine("点个在看吧!");
Response.Write("点个在看吧!");
alert("点个在看吧!")
echo "点个在看吧!"

你点的每个“在看”,我都认真当成了喜欢


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web Design Handbook

Web Design Handbook

Baeck, Philippe de 编 / 2009-12 / $ 22.54

This non-technical book brings together contemporary web design's latest and most original creative examples in the areas of services, media, blogs, contacts, links and jobs. It also traces the latest......一起来看看 《Web Design Handbook》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

MD5 加密
MD5 加密

MD5 加密工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具