Hello Pythonistas. I’m going to present to you a method for debugging your Python scripts that should greatly increase your productivity if you aren’t already doing something similar. Recently, I was making some changes to a script that I had been working on, when I realized it had become a little too bulky to be just a quick script. I got to the point where I had too many variables to remember off-hand, especially when working on the script intermittently. The result was less and less progress as the code expanded. Previously, I wrote about using IDLE , and how it can even out the learning curve when doing something for the first time. Using your primary IDE alongside IDLE is crucial, for the same reason this Python developer explains. Taking it one step further, I’ll outline a way to develop your code through a pong analogy.
Pong is a two player game between two humans; programming is a one player game between man and machine. Writing your code and debugging is a lot like playing pong with yourself – you hit the ball toward one side, set down your controller, pick up the other controller, and return the volley back to the original side. In this analogy, the one side of the screen is the environment where you do the bulk of your coding, the other side is IDLE. When creating and debugging code, you should be spending time on “both sides of the screen”. Each environment has their own pros and cons. Your primary development environment (for me, notepad++ works fine) has syntax highlighting, auto-completion, and information about functions. IDLE on the other hand, lets you interact directly with variables and statements, but you cannot enter in more than one statement at a time. The technique I’m about to describe will help you make optimal use of both of these tools.
With IDLE you can run your code and examine the variables afterwards. First, create a new file or open an existing one (ctrl+n, ctrl+o) and then Run –> “Run Module” (F5). This will compile and execute the code and launch an IDLE environment where all your variables and objects still exist. They can be accessed with:
I won’t go into exactly what each of these mean, because it is probably better explained already here. Essentially you’ll be able to see the values of any variables or objects you have, after the code is done executing. Why is this good? Because if you have errors or aren’t quite sure why something isn’t working the way you intended, you can peek at the variable values simply by typing in their name. This isn’t as precise as step by step debugging as can be done in some development environments, but it is the next best thing and is extremely simple to do. Let’s look at an example with an intentional out of index error:
Here we have a list and we’re addressing items by their place in the list by index (k). We also have some action removing elements from the list as we loop through each index. If the code is run it will error out before the last print statement is reached. But instead of going back to our code and trying to imagine each step of the code to figure out what went wrong (which is sometimes near impossible given more complex code), why not just look at the variables as they existed before the code halted? It’s like working with a partially completed puzzle instead of starting from scratch:
Now it is extremely easy to go “Oh, the first element was added and removed, which is why the ‘s’ was added instead of the ‘e’, followed by the index out of range error.” It is important to know basic looping and indexing, and to be able to see it with your mind’s eye, but once you start working with longer and more complex code it is priceless to be able to examine variables like this. Furthermore, if I want to see what would happen had the code not crashed, you can simply continue coding in IDLE since all your variables are already populated and loaded into memory. For example, if I was in the above environment I could continue working by doing something like
word += ‘et’
Here’s how you get a list of your variables and their contents:
This is where the trial and error of your coding should be done until you are convinced you have the solution worked out. Once you bring back your changes to the shell script and run it a few times, you should now be pasting the code back into your primary environment (picking up the other controller, as it were) and continuing work with the bulk of your code until you come across your next head-scratcher. Rinse and repeat.