前言
这是一个面向初学者的文章. 很多朋友在初学编程的时候很难找出错误,或者对程序运行流程不太清楚. 这个时候调试器就要上场了~ 所以在这里我要以Spyder为例,介绍调试器的用法.
为什么
我们为什么要学会调试
学会调试,对于我们理解程序的运行流程,以及找bug很有帮助. 想一下,如果我们能够在程序运行的时候,实时查看变量是怎么变化,岂不美哉?
为嘛要用Spyder
首先,这是一个面向Python初学者的文章. 考虑到本篇文章的读者可能都是从Anaconda开始的,所以我在此以Spyder为例讲解调试器的使用. 其他IDE的调试功能其实大同小异.
Spyder初体验
熟悉Spyder的界面
我们先来熟悉一下Spyder的界面.
- 最上面有一排按钮,我们俗称工具栏.
- 在左侧,我们可以写代码. 按一下工具栏上绿色的开始按钮,即可开始运行程序.
- 右侧分为上下两栏.
- 上栏中,有三个
选项卡
.分别是Variable explorer
(这个很重要),File explorer
,还有Help
(后面两个基本没啥鸟用) - 下栏叫做
IPython console
,我们俗称为控制台. 一般来说,运行代码时候的输出,会在控制台里面看到. 当然,我们可以在没有运行代码的时候,在In [n]:
(n是几不用关心)后面打入命令与控制台交互.
- 上栏中,有三个
用Spyder运行示例代码
现在我们在左侧代码区域,粘贴下面的代码.
a = 0
for i in range(10):
i += 1
a += i
print(a)
然后按一下绿色的开始按钮,我们可以在控制台中看到输出. 输出:
55
给初学者的注释: i += 1 等同于 i = i + 1.
调试目标
我们想知道每一次for循环进行的时候,a和 i的值是怎么变化的.
朴素的 print 调试法
这个方法自古以来就有了. (胡说,古代哪有Python)
在没有调试器的漫漫长夜中,这种直接输出到屏幕上的调试方法最为实用.
既然我们想要看a和i在每一次for循环中的值是多少,那么我们直接print出来就好了! 所以我们把代码修改成:
a = 0
for i in range(10):
i += 1
print("此时i的值为:",i) # 在i变化后立马print,看看它的值是多少
a += i
print("此时a的值为:",a) # 在a变化后立马print,看看它的值是多少
print(a)
运行结果是这样的:
此时i的值为: 1
此时a的值为: 1
中间省略无数个此时
此时i的值为: 10
此时a的值为: 55
55
这样我们就能看出来每次for循环的i和a的变化情况了.
但是这样太麻烦了,而且满屏幕的i的值,a的值,看得人眼晕. 而且当变量很多的时候,我们要加很多print. 最后到了提交之前,还要记得把自己打的这些print给删除掉.
那么,有没有更直观,更优雅的方法呢?
隆重登场的调试器法
我们如果要运行程序,只需要点击工具栏中那个绿色的开始按钮就可以了.
但是这只是单纯的运行. 它会像IDLE一样,正常运行程序,没有调试没有逗留.
第一招式 - 逐行调试
进入调试模式
想要开始调试,我们需要按下图中所示的1号按钮(Debug File).
然后我们再点击一下下图中红色箭头所指的
Variable explorer
.- 红色箭头: 一定要记住,我们一定要切换到下图中红色箭头所指的
Variable explorer
,这样我们才可以看到变量此时的值. (不过因为我们还没有执行第一行代码,所以这里是空的.) - 蓝色箭头: 它所指的地方,上面有个
---->
的符号,并且后面有行号1.这代表当前调试器将要(还未)运行第一行代码. (划重点,不要搞错,「将要」)
- 红色箭头: 一定要记住,我们一定要切换到下图中红色箭头所指的
开始逐行调试
现在,按下图中所示的2号按钮**(以下称为Run Current Line)**,开始在调试器里面运行下一行代码.
我们可以看到,Variable explorer
里面多出了变量a
.
其中Name
代表这个变量的名称,第二栏Type
是这个变量的类型.而最后一栏Value
是该变量的值.(Size不用管,暂时用不上.)
并且控制台中的---->
符号指向了第二行. 说明第一行执行完毕,再次点击将执行第二行.
举个例子:
以图中的变量a
为例,这个变量的名称是a
,它的类型是int
,值为0
.
(正好也和我们预期的情况相同–我们执行了一句a=0
)
我们接着点刚才的Run Current Line.可以看到,Variable explorer
中又多出了第二行变量i
.并且此时控制台中的---->
指向了第三行.
这说明此时,i
的值为0
,a
的值也为0
.
我们点击Run Current Line(这是第三次).发现i
的值由0
变为1
.
再点击一次Run Current Line(这是第四次),a
的值也变成了1
.
注意一下,经过四次逐行执行,控制台输出如下:
ipdb> None
> c:\users\rise\desktop\temp.py(2)<module>()
1 a = 0
----> 2 for i in range(10):
3 i += 1
4 a += i
5 print(a)
我们可以看到,---->
符号指向第二行(for所在的那行).
这说明此时第一次for循环执行完毕.由于还有后面的循环,所以这里程序要跳回for循环的起始位置,继续进行剩下几次循环.
我们通过逐行调试,可以很直观清楚地跟踪程序的运行过程.
如果我们想中途停止此次调试,只需要点击一下6号按钮,即Stop Debugging
.
这就是逐行调试了.
小总结
来总结一下:
- 要开始调试,需要点击
Debug File
. 点击之后,会进入调试模式. - 一定记得切换到
Variable explorer
,这样才能查看变量的变化情况. - 点击
Run Current Line
,运行第一行代码. - 继续点击
Run Current Line
这个按钮,会按照程序逻辑运行下一行代码. 直至执行完毕为止. - 通过点击
Stop Debugging
,我们可以停止调试.
在上述的调试过程中:
Variable explorer
中将显示当前存在的所有变量.Type
表示该变量的类型Value
一栏将显示变量的值.(不要看走眼,不是Size
一栏)- 在控制台中,我们可以通过
---->
这个符号所指向的行数,看到即将被执行的代码是哪一行.
第二招式 - 断点调试
断点调试顾名思义,是可以在某一行(或多行)设置断点,对该行进行调试. 而逐行调试是对每一行进行调试. 断点调试是更有针对性的调试方法.
如果你能搞清楚逐行调试,那么断点调试也不难.
设置断点
如图. 双击某一行行号前面的空白处,之后在这个地方会出现如图所示的小红点. 这个小红点就是我们所说的断点.
开始调试
如图所示,我们现在在第3行,第4行设置两个断点.
我们按Debug File
开始调试代码.
此时可以看到,控制台里面的显示是这样的:
ipdb> > c:\users\rise\desktop\temp.py(3)<module>()
1 a = 0
2 for i in range(10):
1---> 3 i += 1
2 4 a += i
5 print(a)
其中,行号前面的1和2,代表我们设置的两个断点. 所以此时即将运行第一个断点处,即第三行.
继续调试
程序的执行此时暂停.我们要让它继续运行,需要按一下第五个按钮,即Continue executation until next breakpoint
:
这个按钮的意思就是,继续执行直到下一个断点.
因为我们第二个断点设置在第四行,所以代码将继续执行,在将要执行第四行的时候会暂停.
断点调试小总结
我来总结一下断点调试的几个步骤.
- 双击行号前面的空白处,以设置断点
- 点击
Debug file
开始进入调试 - 在调试过程中,通过
Variable explorer
观察变量的值 - 点击
Continue executation until next breakpoint
执行到下一个断点处. - 通过点击
Stop Debugging
,我们可以停止调试.
调试器总结
几点需要注意的地方:
- 每次打开Spyder的时候,右上方区域默认显示的是
Help
. 所以我们需要手动切换到Variable explorer
. - 在调试的时候,
---->
指向的是即将执行的代码,而不是已经执行的代码. - 当一次调试完毕后,开始第二次调试的时候,
Variable explorer
不会自己清空. 这点一定要注意,上一次调试残留的变量的值仍然会留在Variable explorer
里面. 所以我们可以按一下下图所示的按钮清空.
写在最后
调试是IDE中很重要的一个功能. 这篇文章虽然字很多,但实际上用起来是很简单的,它并不复杂,而且很适合新手. 如果我们学会了调试器的使用,那么写代码将会事半功倍.
另外,其他的IDE的调试功能也是大同小异.大家可以探索一下!
那么最后呢,就祝各位学有所成~ Cheers!
(未完待续,因为可能会有补充)
上次修改於 2019-10-28