Debugging Interactively with Python

Nilesh Kesar
Revel Systems Engineering Blog
6 min readDec 4, 2023

Debugging is the process of finding and fixing errors or bugs in the source code of any software. When software does not work as expected, computer programmers study the code to determine why any errors occurred. They use debugging tools to run the software in a controlled environment, check the code step by step, and analyze and fix the issue. — AWS

Generally, when we think about bugs when it comes to programming, the definition that comes to mind is they are flaws in our code. Finding these flaws can be difficult, tedious, and very time-consuming. In short, we spend a lot of time doing these tasks, while each bug can be different the techniques we use to find the bugs are generally the same. In our debugging tool kit we might already have a few tricks up our sleeve such as print statements, but did you know about interactive debuggers?

Interactive Debuggers

Interactive debuggers can be one of a developer’s most useful tools, as it provides them with a step-by-step way to walk through the code as it executes. Some debuggers are baked into IDEs while others are available through the terminal/command line. Either way, the debugger we use has its pros and cons, but all of them will help us figure out what's going faster and easier. The debugger can provide a lot of useful information such as a stack trace and the variables’ current values.

Types of Interactive Debuggers

In this article we will be talking about some Python interactive debuggers, please note that even though we are using Python a lot of languages have interactive debuggers, for example in a different article I talked about using Delve for Golang which can be found here.

Some examples of interactive debuggers are:

PDB

PDB stands for Python Debugger and is a part of the standard Python library, meaning no extra installs (woo hoo). This interactive debugger is a command-line debugger. To use it all we need to do is import it and run the Python application as soon as it hits the PDB trace statement it will stop execution and wait for user input.

import pdb
def add(a: int, b: int) -> int:
result = a + b
pdb.set_trace() # sets a breakpoint

return result

def main():
add(1,4)

if __name__ == "__main__":
main()

In the example, the code will run until it hits pdb.set_trace(). This creates a breakpoint. When the code hits the breakpoint it will stop and wait for user input. The input can be a PDB command (some common ones are below) or we can call a variable to see what it currently is or we can run Python code directly to test something out. See the examples below:

In the picture above we are calling the result variable to see exactly what it contains.

In the code above we are calling Python commands to see if manipulating the current variable stored value will it fix our code.

In the code above we are calling PDB commands to list out the lines so we can see where we are and what has been executed and what has not.

You can copy the code above and execute it yourself to try it out. Some quick commands for you to know:

Commands
----------------------------
n # this stands for next and is for telling the debugger to excute the line of code you are on and go to the next line. If a function is being excuted on that line it will *not* go inside the function
s # this stands for step and is for telling the debugger if this line is calling a function to go inside the function.c # this stands for continue and will continue excuting your code until it hits a breakpoint.b <line number> # this command stands breakpoint and takes a line number as an argument this command is used to set new breakpoints as the code is runningl # this command stands for list and let you see the source code this is normally the 11 lines at a time from your current linell # this command stands for long list and lets you see all the source code for the function your in. (note this avaible after python 3.2)q # this stands for quit and will quit the debugger

PUDB

PUDB is a visual interactive debugger that is actually a command line debugger but looks like how an IDE interactive debugger would look. Note that PUDB is a separate Python library so you would need to install this using your Python package manager.

I have highlighted each section to make it a little easier to see what area I’m talking about. In pink on the top left are the code and the line numbers. This lets us see what code has been executed and what will still needs to be executed. You can also hit certain keyboard keys to add things like breakpoints, step in a function, or go to the next line. The orange in the top right is where all variables that are currently in scope are defined (Globals and function level). The gold in the middle right is the current state of the stack, which we can use to go to the files and lines and see how you get to the function you currently are on. The red in the bottom right is all the breakpoints. The green in the bottom left is where you can run Python code to test or manipulate the current variables.

VS-Code Debugger

VS Code Debugger is an IDE debugger meaning it runs in your IDE and not the command line. There are many IDEs that support interactive debuggers, since VS Code is a popular IDE I am using this one, but note that others also have it such as PyCharm.

On the left, the blue box shows a bug and play icon which we can click. This will open a window up where we can click run and debug you specify what you will be debugging in our case a Python file. This will start the debugger, and you can see the call stack, the current variables, the variables you want to watch for, and the breakpoints you want to use. In the green, at the top middle, you will see continue, next, step in, step out, restart, and stop.

Next time you are debugging consider using an interactive debugger to help you. These are just a few examples but there are others, I hope this helps you solve your next bug!

--

--