CyberBrain: Debugging Python Programs Like A Pro
By: Kaustubh Gupta
Tags: Visualization, Python, Vscode, Debugging, Programming

The word debugging means fixing potential bugs in a program. The basic steps in debugging include recognizing that a bug exists, isolating the source of the bug, identifying the cause of the bug, determining a fix for the bug, applying the fix and test it. — Computer Programming Principles/Maintaining/Debugging, WikiBooks

Introduction

The above lines clearly show a path of how we perform debugging in most cases. It is almost not possible to write a complete a full program at one go from the scratch without committing a mistake (if you can, well…). When we talk about debugging, we are trying to solve a set of errors on why the program is not working. In Python, we encounter these types of error:

1. Failed To Compile (Syntax Error)

2. Abnormal Exit

3. Program runs but gives the wrong result

4. Program is correct but consumes a lot of resources.

The first one can be solved by referring to the documentation or the language definition because the error is not logical in terms of user interference, abnormal exit requires a thorough review of the code to look out for any exceptions, and the last one requires a good understanding of the underlying Data Structures to optimize the code for the best case. The third one is the most encountered error in most of the cases and we spend quite a lot of time fixing them. This article focuses to solve this error at ease.

Current Situation

Whenever our program encounters an error, these are some of the common ways we currently follow:

1. Using Print() statement: One of the obvious and quickest ways to debug a code is printing the intermediate variables and checking if the code execution is going in the order. Almost everyone uses print statements to debug their code and the developer of Python, Guido van Rossum also supports this. See an example below:

Image by Author

You must have guessed the error in this code, but suppose you didn’t. If you run this program, this will be the output for this:

Enter number one: 5

Enter number two: 5

55

The program ran but the output is wrong. To fix this, you can simply print the type of variables a and b are.

<class 'str'>

As they are strings, they are getting concatenated. Adding int function to these will solve this error.

Enter number one: 5

Enter number two: 5

10

A simple print statement can do the job but in this case, you were required to know where to place the statement. We will revisit this example while exploring our interactive solution.

2. Logging: It is a configurable technique to catch bugs. It is also easy to manage and provides richer context as compared to print statements. But the issue here remains the same. We need to know where the logging needs to be introduced.

3. Debuggers: It is the most powerful way to debug and has a lot of features for the user. An added advantage of debuggers is that they don’t require familiarity with the code. In Print and logging, you need to know where the code is broken but a debugger can simply point out the root cause more easily. But debuggers require a lot of effort plus you actually need to know how to use them.

If all of these have some or the other issue, then what is the solution? That’s where I introduce you to CyberBrain.

CyberBrain

Considering all the cases above, no tool in the market is powerful as a debugger and easy to use as a print statement. We want a tool that requires the least amount of effort but still provides richer information. CyberBrain aims to provide this by visualizing the inner working of the program. The setup of this library is a two-step process:

1. Installing the library via pip command:

pip install cyberbrain

2. Installing the VSCode extension: Currently, the library only supports VSCode IDE and GitPod. I think most of the developers use VSCode (if not, switch as soon as possible!), and installing the extension is not a hard task. Search for this extension and install it:

Now we are all set to debug our programs. Let’s apply this to the example we discussed above:

I have added a decorator called @trace on the function summ(). This decorator allows CyberBrain to trace back all the changes in the function and present an interactive tree-like visualization:

The output of the program above

You will also get a developer’s tool window (Chrome Dev Tools) with the opened console which presents all the variables values and the hovering done by the user. It also truncates all the variables which hold large values and are difficult to present on Graph.

Now let’s solve this bug using this interactive tree. Hover over the tree and see you find anything noticeable? Can you spot the error?

Image by Author

Right, the values of a and b are quoted which means they hold string type values, and therefore the result returned by the function is the concatenation of both these strings!

Let me correct the code and see the tree after the code modification:

Output after code modification

As you can see, now the values are not in quotes and the result is correct. This means they are numerical and hence the addition gave the right result! Let’s consider another problem to better visualize a program. This program is also available in the creator Github repo:

Code by Author

After running the code, you will get an output like this:

The output of the code above

Now let’s understand this:

Initially, the lines variable was formed by taking arguments day and ordinal. Then another state of lines variable came using old lines variable state, day, and gifts variable. And at the end, this resultant lines variable was modified without the intervention of other variables to return the final state of the variable lines. This interpretation was only done based on the chart above and I had no clue what the code was doing. After comparing what the code does and what the tree returned, all things made sense!

Another function of this library is that if you have a loop in your function, then you can see the variables at each step and modify the counter value too!

Loop counter can be defined by the user

Conclusion

This was all about the library CyberBrain. Some points I want to mention is that the library is under heavy development and v1.0 is yet to release. Currently, there is no support for async and multithreaded programs. You cannot use @trace decorator more than once in your program. That means it can only trace one function for now but the developer of this library has plans to include all these features in the upcoming versions.

If you like my way of writing and want more articles then make sure to follow me on my socials so that you don’t miss my new articles. Also, you can reach out to me for any doubts, queries, or potential opportunities!

1. Linkedin — in/kaustubh-gupta/

2. Twitter — @Kaustubh1828

3. GitHub — kaustubhgupta

4. Medium — @kaustubhgupta1828

Reference: This article has been inspired by this talk: “Let’s Rethink Debugging” — laike9m (PyCascades 2021)

My Other Articles: