Debugging workflow
You have to understand that in fact you are using different integration of the Python debugger pdb
and ipdb
(which uses pdb
and which can be accessed using the module ipdb
). I hope this trivial example will help you with using it better.
Suppose you want to debug this code:
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
Quick first debugging using iPython %debug
%debug
The first thing I do is to call pdb from iPython using the magic command %debug
, you can set it as a default mechanism using %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
Once you have lunch pdb
. You can find all command in the official docs or you can use the command h
to display them. In this stage the only commands that I use are:
p
: prints the variables that you specify
pp
: pretty prints
args
: if you are inside a function it prints the arguments
pp locals()
: can be useful to print all the variables but most of
the times it is a mess!
!
use it if you want to avoid conflicts with the commands listed in h
whatis
variable_name: equivalent of type(variable_name)
u
: Move the current frame one level up in the stack trace (to an older frame).
d
: Move the current frame one level down in the stack trace (to a newer frame).
q
: when you finish you can use q for quitting
In our case:
ipdb> pp a,b,c,d
(25, '5', 456, '23')
Or ipdb> !a,b,c,d
(no space between esclamation mark and first value).
It's clear that b and d are strings in case we can use:
ipdb> whatis b
<type 'str'>
Going deeper using break-points
70% of the times %debug
points you to the solution. When you need more features like breakpoints is time to use Spyder. In this case, we want to understand why b
is a string we put a breakpoint next to it (double-clicking next to the line number in the editor window). I find much better to use the standard Python console instead of the IPython console for debugging so select the console before starting debugging:

Then open the variable explorer
if there are any variables delete them. I use Ctrl+F5 to start the debugging you can use the buttons on the top but I prefer to use their shortcuts shown below:

(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
Now we have located the error. We can also test a solution we repeat the step until 12 and we set to_s = False
(Pdb) to_s = False #!to_s = False to be on the safe side
It works. One important feature using the standard pdb in the Python console, is that you have auto competition and you can use the variable explorer instead of using whatis
and pp
:

Using the variable explorer you can also change the value of the variables which makes the things even quicker.
Conditional breakpoints
Another more clever way to locate the error is to use conditional breakpoint (Shift+F12) a great advantage of Spyder is going to debug and use list breakpoints. Conditional breakpoints are activated when the condition is True
In our case, we want to locate where b becomes a string so the condition is: type(b) == str
. I usually place a lot of conditional breakpoints and see which ones meet the condition. For doing so don't use Shift+F12 but place normal breakpoints double-clicking next to the line and go to Debug->List breakpoints and copy and past the condition in the table to every breakpoint as shown in the figure below.

From here the commands to use are:
(Pdb) c # go to the first
(Pdb) u # it helps to understand when it happened
(Pdb) d # come back to the breakpoint