Debugging in Python
One of the reasons why I love the Python programming language is because of how easy debugging is. You don't need a full blown IDE to be able to debug your Python application. We will go through the process of debugging a simple Python script using the pdb
module from the Python standard library, which comes with most installation of Python.
Let's take a look at the following simple snippet:
def funcA(first_val, second_val):
result = (first_val*2) - (second_val/4)
return result
def functionB(first_val=23, last_val=72):
response = funcA(first_val, last_vale)
result = response * first_val / 7
return result
functionB(33,88) # we are evaluating the funciton.
If we try running the snippet above, we would get an error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in functionB
NameError: global name 'last_vale' is not defined
To find out what is wrong with this snippet, we need to know where we should place our breakpoint. A breakpoint tells the Python interpreter to pause execution at a particular point in our application.
From the error message above, we can infer that the problem is coming from the functionB
function. But depending on our expertise, we might not be sure what is causing the error.
To debug the problem, we would add a breakpoint to the start of our functionB
implementation
# we would place our break point here
import pdb
pdb.set_trace()
response = funcA(first_val, last_vale)
result = response * first_val / 7
return result
The breakpoint in this case is the two line import pdb;
and pdb.set_trace()
. With these two lines in place, if we try running our application again, we would get an output like this
The interface looks similar to that of the interactive shell that Python provides. We can test out the values passed into the function by typing them out:
To step to the next line, we use the key n
, which means next
, to step down the code line by line
We can see from the above that as we moved to the next line, the error we encountered earlier on, came up again. So we are certain that the problem in our code happens on the line which we just ran.
To get python to continue execution of the program, we type c
which means continue
and the program executes as usual.
Now assuming we fixed our implementation by ensuring that the correct name of the variable is used and removed the breakpoint because we don't want the program to pause
def funcA(first_val, second_val):
result = (first_val * 2) - (second_val / 0)
return result
def functionB(first_val=23, last_val=72):
# we would place our break point here
response = funcA(first_val, last_val)
result = response * first_val / 7
return result
functionB(33, 88)
We would run into a different kind of error this time
$ python sample.py
Traceback (most recent call last):
File "sample.py", line 13, in <module>
functionB(33, 88)
File "sample.py", line 8, in functionB
response = funcA(first_val, last_val)
File "sample.py", line 2, in funcA
result = (first_val * 2) - (second_val / 0)
ZeroDivisionError: integer division or modulo by zero
We might not be sure where the error is coming from if we are just getting familar with python but with pdb
we can progress incrementally to where the error occurs.
We know that the starting point of our application is in functionB
function so we would place our breakpoint there and step through the application line by line
We are already familiar with n
moving to the next line. But now we are seeing s
. This means step
which moves the flow of control into the functionA
. In functionA
we keep on pressing n
line by line till we get to the part of our code that throws the error.
There are actually more commands, all of which can be explored at https://docs.python.org/2/library/pdb.html. But For your day to day debugging needs, n
, s
and c
is all you need.
One thing we should keep in mind should we choose to debug our application this way is to ensure that we don't use single word values as variable names in our application.
Take for instance
import pdb
pdb.set_trace()
n= 84
s = 45
c = 23
If we wanted to navigate to the next line and we typed n
, we would run into a conflict because n
has special meaning in pdb
and our variable is also named n
.
Happy Debugging.