How many times have you been stuck in a situation where you have to change someone else's code? If you're part of a development team, you're more than you want to be in this situation. However, Python has a neat debugging feature (like most other languages), which is handy in this case. This is a quick tutorial and hopefully it will make your coding life easier.
1. A messy procedure
For the purposes of this tutorial, let's look at the following simple program.
This program receives two command-line arguments, and then performs addition and subtraction operations.
(assuming that the user entered a valid value, we do not have error handling in the code.) )
Import SYS
def add (num1=0, num2=0): return
int (NUM1) + int (num2)
def sub (num1=0, num2=0): return
Int ( NUM1)-Int (num2)
def main ():
#Assuming Our inputs are valid numbers
print sys.argv
addition = Add (sys.ar GV[1], sys.argv[2])
print addition
subtraction = Sub (sys.argv[1], sys.argv[2])
print subtraction
if __name__ = = ' __main__ ':
Main ()
2. PDB
Python provides a useful module PDB, which is actually an interactive source code debugger.
You need the following two lines of code to use this module.
Import PDB
pdb.set_trace ()
Take a look at the program we've modified, which contains some breakpoints.
Import PDB
import sys
def add (num1=0, num2=0): return
int (NUM1) + int (num2)
def sub (num1=0, num2=0): return
Int (NUM1)-int (num2)
def main ():
#Assuming Our inputs are valid numbers
print sys.argv
Pdb.set_trace () # <--break Point added here
addition = Add (Sys.argv[1], sys.argv[2])
print addition
Subtraction = Sub (sys.argv[1], sys.argv[2])
print subtraction
if __name__ = ' __main__ ':
Main ()
3. Program execution Trigger Debugger
Once you have set the breakpoint, you can execute the program as usual.
The program will stop executing at the first breakpoint encountered.
[' debugger.py ']
>/users/someuser/debugger.py Main ()
-> addition = Add (sys.argv[1), sys.argv[2])
(PDB)
We set a breakpoint on line 14th, so we can see that the next line that will be executed is line 15th. As you can see, the program has stopped before executing to line 15th.
Here we have a few options, let's take a look at some debugging instructions in the following steps.
4. Next line->n
In your debugger prompt, enter N to run to the next line.
>/users/someuser/debugger.py Main ()
-> addition = Add (sys.argv[1), sys.argv[2])
(Pdb) n
>/ users/someuser/debugger.py Main ()
-> Print Addition
This executes the current line of code and prepares to execute the next line.
We can use N to execute the entire program line by row, but it's not really useful.
As you may have seen, the PDB actually does not go into our add function. Next, let's look at some other options that make debugging more interesting.
Attention:
A cooler feature is that you can click the ENTER key to execute the previous command (in this case, just instruction N).
5. Print->p
Next, we start the debugger again. (You can jump to the end of the PDB or until the next breakpoint by clicking C, because we don't have any other breakpoints in the program, and all the programs will be done.) )
[' debugger.py ', ' 1 ', ' 2 ']
>/users/someuser/debugger.py Main ()
-> addition = Add (sys.argv[1), sys.argv[2])
(PDB)
Now, if we want to know what the SYS.ARGV contains, we can enter the following:
-> addition = Add (Sys.argv[1], sys.argv[2])
(PDB) p sys.argv
[' debugger.py ', ' 1 ', ' 2 ']
(PDB) p sys.argv[1 ]
' 1 '
(Pdb)
Using this method, you can fairly easily see what values are actually stored in the variable.
Now we're going to go inside the addition function.
6. Single Step->s
We can use "s" to go inside the addition function.
(PDB) s
--call--
>/users/someuser/debugger.py (4) Add ()
-> def add (num1=0, num2=0):
(PDB) n
>/users/someuser/debugger.py (5) Add ()
-> return int (NUM1) + int (num2)
(PDB)
This will take us inside the addition function, and now we can use N, p, and other operation instructions inside the addition function.
Clicking "R" at this point will take us to the return statement that entered the function earlier.
This instruction is useful if you want to quickly jump to the end of a function.
7. Add breakpoints Dynamically-> B
Earlier, we set a breakpoint using Pdb.set_trace () before the program was run.
However, often after the debugging session has started, we want to add breakpoints in a particular place in the program.
Here we can use the option "B" to achieve this goal.
We re-start the execution of the program.
[' debugger.py ', ' 1 ', ' 2 ']
>/users/someuser/debugger.py Main ()
-> addition = Add (sys.argv[1), sys.argv[2])
(PDB)
At this point I set a breakpoint on line 18th.
-> addition = Add (Sys.argv[1], sys.argv[2])
(Pdb) b
Breakpoint 1 at/users/someuser/debugger.py:18
( PDB) c
We are in add--
3
>/users/someuser/debugger.py () Main ()
-> print subtraction
(PDB) p subtraction
-1
(PDB)
From the above we can see that the PDB jumps to line 18th and waits for the next instruction.
Also, the PDB assigns a number to the breakpoint (1 in this case). For future execution, we can enable or deactivate the breakpoint by opening or disabling the breakpoint number.
8. List->l
Sometimes when you are debugging, you may forget where you are in the code at this time. In this case, using "L" will print out a friendly summary that will show you where you are in the code at the moment.
[' debugger.py ', ' 1 ', ' 2 ']
>/users/someuser/debugger.py Main ()
-> addition = Add (sys.argv[1), sys.argv[2])
(Pdb) L
10 def main ():
#Assuming Our inputs are valid numbers print sys.argv Pdb.set_trace () # <--break Point added
-> addition = Add (sys.argv[1), sys.argv[2])
16 print addition subtraction = Sub (sys.argv[1], sys.argv[2]) Print Subtraction
9. Dynamic allocation of variables
During a debugging session, you can assign variables to help you debug, knowing that this is also helpful for you. For example:
[' debugger.py ', ' 1 ', ' 2 ']
>/users/someuser/debugger.py Main ()
-> addition = Add (sys.argv[1), sys.argv[2])
(Pdb) n
We are In add--
>/users/someuser/debugger.py () Main ()
-> print addition
(PDB) p addition
3 #<--- Addition here is 3
(PDB) addition = ' It now string ' #<---We changed the value of Additon
(PDB) n
th Is are now string #<---Now when we print it we actually gets it as a string. That we just set above.
>/users/someuser/debugger.py Main ()
-> subtraction = sub (sys.argv[1), sys.argv[2])
Attention:
If you want to set some variables such as n (that is, the PDB directive), you should use this instruction:
10. End->q
Finally, if you want to end debugging at any point in the code, you can use "Q" and the program being executed will terminate.
11. Extended Reading
This article only touches on the surface usage of the PDB, but you can do more with the PDB (PDB documentation).
People using Ipython can find a better debugger in ipdb, which provides tab supplements, syntax highlighting, and other cool features.