Debugging in Python

Published Jul 10, 2017
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

snippet.PNG

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:
snippet.PNG

To step to the next line, we use the key n, which means next, to step down the code line by line
snippet.PNG

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

snippet.PNG

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.

Discover and read more posts from Oyeniyi Abiola
get started
Enjoy this post?

Leave a like and comment for Oyeniyi

19
Be the first to share your opinion

Get curated posts in your inbox

Read more posts to become a better developer