调试工作流程
您必须了解,实际上您正在使用Python debugger pdb 和ipdb 的不同集成(使用pdb 并且可以使用模块ipdb 访问)。我希望这个简单的例子能帮助你更好地使用它。
假设你想调试这段代码:
def Waiting_fun(): #1 line number one
for i in range(100): #2
pass #3
#4
def New_sum(lista, to_s = False): #5
result = 0 #6
print 1 #7
for i in lista: #8
print "summed" #9
result +=i #10
Waiting_fun() #11
if to_s: #12
result = str(result)
return result
a = New_sum([1,4,5,7,8])
b = New_sum([1,4],1)
c = 456
d = New_sum([6,8,9],1)
final_result = a*b*c*d
Out: Type error
使用 iPython %debug 进行快速首次调试
%debug
我做的第一件事是使用魔法命令%debug 从 iPython 调用 pdb,您可以使用 %pdb 将其设置为默认机制。
%debug
> /home/opdate/Desktop/test.py(23)<module>()
19 a = New_sum([1,4,5,7,8])
20 b = New_sum([1,4],1)
21 c = 456
22 d = New_sum([6,8,9],1)
---> 23 final_result = a*b*c*d
一旦你吃过午饭pdb。您可以在official docs 中找到所有命令,也可以使用命令h 显示它们。在这个阶段,我使用的唯一命令是:
-
p :打印您指定的变量
-
pp : 漂亮的照片
-
args: 如果你在函数内部,它会打印参数
-
pp locals() :可用于打印所有变量,但大多数
时代一团糟!
-
! 如果您想避免与h 中列出的命令冲突,请使用它
-
whatis variable_name:相当于类型(variable_name)
-
u :将当前帧在堆栈跟踪中上移一级(移至较旧的帧)。
-
d :将当前帧在堆栈跟踪中向下移动一级(到较新的帧)。
-
q : 完成后可以使用 q 退出
在我们的例子中:
ipdb> pp a,b,c,d
(25, '5', 456, '23')
或ipdb> !a,b,c,d(在感叹号和第一个值之间没有空格)。
很明显 b 和 d 是字符串,以防我们可以使用:
ipdb> whatis b
<type 'str'>
使用断点更深入
70% 的时间%debug 将您指向解决方案。当您需要更多功能(例如 breakpoints)时,就该使用 Spyder。在这种情况下,我们想了解为什么b 是一个字符串,我们在它旁边放了一个断点(在编辑器窗口中双击行号旁边)。我发现更好使用标准 Python 控制台而不是 IPython 控制台进行调试,因此在开始调试之前选择控制台:
然后打开variable explorer如果有任何变量删除它们。我使用 Ctrl+F5 开始调试,您可以使用顶部的按钮,但我更喜欢使用如下所示的快捷方式:
(Pdb) c # we go to the breakpoint
(Pdb) s # we step into the function
(Pdb) args # we see what parameters are inserted
(Pdb) s # going step-by-step
(Pdb) ⏎ # series of Enters go line by line quicker
#Here I'll use whatis command but in fact I just look to
# the type in variable explorer of spyder.
(Pdb) whatis result #check if result is still int
(Pdb) unt #or until -useful to exiting from loops see doc.
(Pdb) n # we don't enter to the Waiting_fun function
(Pdb) s # going step-by-step
(Pdb) whatis result #we find that there the int is converted
(Pdb) j 6 # for double checking we jump back to 6 were the result is assigned
# We may be tempted to j(ump) to line 12 but doing so we would skip all the code
#for avoiding a series of `s`,`unt` and `n` we can use this solution:
(Pdb) tbreak 12 #set a new temporary breakpoint. Also `b` it's ok most of the time
(Pdb) c # go to it
(Pdb) j 6 # we jump to 6 the code we jump is NOT executed
(Pdb) whatis result# we find that if we jump 12-13 result is still int
现在我们找到了错误。我们还可以测试解决方案我们重复该步骤直到 12 并且我们设置 to_s = False
(Pdb) to_s = False #!to_s = False to be on the safe side
它有效。在 Python 控制台 中使用标准 pdb 的一项重要功能是,您可以进行自动竞争,并且可以使用变量资源管理器来代替 whatis 和 pp:
使用变量浏览器,您还可以更改变量的值,从而使事情变得更快。
条件断点
另一个更聪明的定位错误的方法是使用条件断点 (Shift+F12) Spyder 的一个很大的优势是调试和使用列表断点。当条件为True 时,条件断点被激活。在我们的例子中,我们想要定位b 变为字符串的位置,因此条件为:type(b) == str。我通常会放置很多条件断点,看看哪些符合条件。为此,请勿使用 Shift+F12 而是在该行旁边双击普通断点并转到 Debug->List breakpoints 并复制并粘贴条件表到每个断点如下图所示。
从这里使用的命令是:
(Pdb) c # go to the first
(Pdb) u # it helps to understand when it happened
(Pdb) d # come back to the breakpoint