A gentle introduction to print statement debugging
This blog was originally published on Substack. Subscribe to ‘Letters to New Coders’ to receive free weekly posts.
If writing code is day, then debugging is night. Dealing with bugs is non-negotiable in coding. In fact, the most skilled programmers are also the best at debugging.
Today, I want to give a gentle introduction to one of the most effective debugging strategies that will be relevant throughout your career: print statement debugging.
If you have already written an entire program, then you’re ready for this tutorial. If you haven’t, feel free to join us and get a sneak peek of this skill that’s waiting for you later in your learning journey.
What is print statement debugging?
Print statement debugging is a fantastic way to trace the behavior of a program to understand where an error occurred, and how to fix it. (Another perk: it requires no additional tools or complex setups.)
This debugging technique involves placing print statements at various positions in your program.
These print statements help elucidate your code’s behavior by generating outputs that reflect:
- The values of variables
- Flow of execution
- The state of your program at various points
These print statements are additional lines that you write into your program. If you owned a coffee shop, you can think of print statements as shift supervisors who are present at the shop, keeping you updated on the status of operations.
Of course, print statements are not placed randomly throughout code. You should place statements strategically at key areas where the state changes or important operations occur, such as:
- Before and after loops
- Inside conditional blocks
- At the beginning, middle, and end of functions
For example, suppose we have written a program that calculates the sum of numbers in a list but it’s not returning the expected result. Here’s the code:
We can add a print statement in the code to help us notice what’s happening in the program.
This added print statement will show us the value of the number being added and the intermediate value of the total
. This helps us trace the execution and verify if the logic inside the loop is correct.
Using print statements for debugging
In its simplest form, the steps to using print statements for debugging are:
- Identifying key areas
- Inserting print statements
- Running the program
- Analyzing the output
- Identifying the issue
- Fixing the bug
- Removing the print statement
Here are some best practices to keep in mind:
Use descriptive messages
Instead of just printing variable values, include context about what those values represent. For example:
Track execution flow
Use print statements to trace the flow, especially in complex logic with multiple branches. For example:
Be strategic (don’t overdo it!)
Overdoing print statements can affect the performance of your application — especially when you’re working in the professional environment.
In professional development, you’ll be working on massive codebases where performance is likely a priority. Instead of using print statements, you may be using a related technique called logging, however you’ll still need to decide where to place logging to help monitor a program. Figuring out exactly where to put print statements without overdoing is not so much a science as it is an art. But the more you do it, the better your judgment will get.
Example: Code with a logical error
Let’s try with an example.
Suppose we have a function that checks if a list of numbers contains any even number(s). The code is intended to return True
if there is at least one even number and False
otherwise.
However, there is a logical error:
Expected output: True
Actual output: False
To debug this, we can add print statements to understand the flow of execution and the values being checked:
Analyzing the output
By running the modified code, we get the following output:
The output shows that the function returns False
after checking only the first number, 1
. This indicates that the else
branch is causing an immediate return of False
, even if there might be even numbers later in the list.
Corrected code
To fix this logical error, we should only return False after checking all numbers in the list:
Corrected output
Now, the output correctly identifies that there is an even number in the list:
Using print statements, we traced the execution flow and identified that the function was returning False
. This allowed us to correct the logic and ensure the function worked as required.
Becoming a professional debugger
Becoming a developer means becoming a debugger too. And print statements are a great way to start getting methodical with debugging. Once you’ve understood print statements and strengthened your debugging skills, you’ll be able to move on to logging for the professional development environment.
Either way, the best way to grow your debugging skills is by making mistakes and getting your hands dirty with debugging.
If you’d like to learn more about debugging, we’ve launched a great beginner-friendly course that covers various debugging strategies: Mastering Debugging: Techniques for Efficient Code Diagnosis.
Happy debugging!
– Fahim