Stop debugging like we are in the 1950
Debugging is one of the inevitable processes that you have to go through if you are writing codes, whatever language you use after developing a couple of functions each calculates some variables that are input to another function, at this point, things start to get complicated, and if the main algorithm you are working on is solving some partial differential equation and you need to assign initial and boundary conditions or even an ordinary differential equation, your code becomes very error prune and the main source of error is usually the flow of values from variable to another, updating an array in the wrong index, branching with a condition that calls two different functions, a lot of scenarios that gets more and more complicated depends on how big is your code and how significant are the changes you made, Here comes the role of debugging your code.
Almost all programming (compiled/interpreted) languages have a debugger where you can create a breakpoint anywhere in your code and when you run the code it stops at the breakpoint so you can have a look at the snapshot of all the variables at this point of the code execution.
let's consider the following very simple python code which calculates the exponent of a list of numbers to the power 2
# debug-example.py
def exponent():
num_list = [10, 20, "30", 40, 50, 60]
calculated_var = []
for i , val in enumerate(num_list):
cal = val ** 2
calculated_var.append(cal)
if __name__ == "__main__":
exponent()
- yet if you run this script in your terminal you will get an error.
C:\MyComputer\test> python -m debug-example
File "C:\MyComputer\test\debug-example.py", line 12, in <module>
exponent()
File "C:\MyComputer\test\debug-example.py", line 7, in exponent
cal = val ** 2
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'
- To debug this code we can use the standard library debugger that is part of the python installation [pdb](https://docs.python.org/3/library/pdb.html)
- Just by adding the pdb ad an argument to python in the terminal and running the command, the debugger will stop directly after
C:\MyComputer\test> python -m pdb debug-example.py
> c:\mycomputer\test\debug-example.py(2)<module>()
-> def exponent():
(Pdb)
- Now you can interact with the pdb in the terminal using the next, step, continue, exit and break commands
> c:\mycomputer\test\debug-example.py(2)<module>()
-> def exponent():
(Pdb) next
> c:\mycomputer\test\debug-example.py(11)<module>()
-> if __name__ == "__main__":
(Pdb) next
> c:\mycomputer\test\debug-example.py(12)<module>()
-> exponent()
(Pdb) next
inside
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'
- Still not very helpful even with this very simple example, in other complicated cases you need to see the current values for all the variables after stepping inside a function.
- So this is the 1950 way of how you debug your code, and if you think that you can find the error only using a print statement good luck, you did not even get to the 1950 way of debugging yet.
- Most of the Integrated Development Environments these days come with an interactive display of the variable explorer where you can see each variable and the current data type (in the case of python) and the value assigned to each variable, some IDE even makes it even possible to visualize arrays to check the values stored in all the rows and columns.
- To check some of the most popular IDEs and their debuggers, you can check this Python wiki page about debugging tools [https://wiki.python.org/moin/PythonDebuggingTools]
- So in this article, I will try to run the same script above with Pycharm
To debug using any of the modern IDE, there are some actions you can use in the IDE to navigate your code in a debugging session
The processes that you will use frequently in the debugging session are
- “Step into ”: get inside the function called in the line one by one
- “Step over”: executes the line without stepping into any of the functions
- “Run to cursor”: run the whole script till the line you put your cursor.
- “Toggle Breakpoint”: to point out the line where you want the debugger to first stop
for the ease-of-use, you can assign a keyboard shortcut to each of the previous actions
Debugging Python code using Pycharm
In the following video, I will be doing exactly the same as what I did in the terminal using the pdb, but I can check visually the variable explorer (bottom right panel) to see how each variable value is updated line by line, I can also open the variable itself to check the value stored in each element (if it is a long data frame or a 2D array), there is also an inline variable explorer where you will find the value of each variable appear in the right part of each line.
I think, using this way of debugging helps way more than the print statement or the pdb in the terminal can do.
Debugging FORTRAN code using VS code
In the next example, I will be debugging a FORTRAN code in VS code
- For simplicity we can assume that the following code and we want to know how the 1D array c is updated in the loop
program matmul
integer :: a(10), b(10), c(10)
a = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/)
b = (/3, 6, 7, 1, 4, 8, 7, 6, 9, 3/)
do i = 1, 10
c(i) = ( a(i)**2 ) + b(i)
end do
end program matmul
- similarly we have the same processes as in Pycharm (Step into, Step over, …) and you can also set up the keyboard shortcuts to be the same also. In VS code a small moving panel will appear once you start the debugging session where you can find all of these debugging processes
- Unlike Python, FORTRAN needs all the variables to be declared at the top of the code, and if you don’t initialize them they will be randomly initialized, and then later when the calculation takes place, a new value will be assigned to a certain position in the array
In the above two examples, you need to set up the whole environment to be able to run and debug your codes, in Pycharm you need a python interpreter defined, and in VS code you need a FORTRAN compiler and a gdb debugger which I installed by installing the GNU compiler collection.
So definitely debugging using any IDE helps more than the print statement of the terminal debugger