Python Debugging Techniques

First things first, let’s define what we mean by “debugging”. Essentially, it’s the process of finding and fixing errors in your code. This can be anything from a simple syntax mistake to a more complex logic issue.

Now, there are several ways to approach debugging, but I like to start with print statements. These allow you to see what values are being assigned to variables at different points in the program. For example:

# This code calculates the area of a rectangle based on user input

# Prompt user for input and convert it to an integer
length = int(input("Enter length: ")) 

# Same as above, but for width
width = int(input("Enter width: ")) 

# Calculate the area by multiplying length and width
area = length * width 

# Print out the result
print("The area of your rectangle is:", area)

Let’s say you run this code and get an unexpected output. Instead of “The area of your rectangle is: 12”, it says “The area of your rectangle is: 0”. This could be due to a variety of issues, but let’s assume for now that the user input is incorrect (i.e., they entered a negative number or zero).

To debug this issue using print statements, we can add them at different points in the code to see what values are being assigned to variables:

# This code calculates the area of a rectangle based on user input

# Prompt user for input and convert it to an integer
length = int(input("Enter length: ")) 

# Add print statement to see what value is being assigned to 'length'
print("Length:", length) 

# Same as above, but for width
width = int(input("Enter width: ")) 

# Add another print statement to see what value is being assigned to 'width'
print("Width:", width) 

# Calculate the area by multiplying length and width
area = length * width 

# Print out the result
print("The area of your rectangle is:", area) 

# The original script had no annotations, making it difficult to understand the purpose of each code segment. 
# By adding annotations, we can easily see what each line of code is doing and why it is necessary. 
# Additionally, the original script did not handle any potential errors or incorrect user input. 
# To address this, we can add a try-except block to catch any potential errors and handle them appropriately. 
# We can also add a check to ensure that the user input is valid (i.e. positive numbers only). 
# This will make the code more robust and prevent any unexpected errors. 



# Prompt user for input and convert it to an integer
try:
    length = int(input("Enter length: "))
    # Check if length is a positive number
    if length <= 0:
        print("Please enter a positive number for length.")
        exit() # Exit the program if input is invalid
except ValueError:
    print("Please enter a valid number for length.")
    exit() # Exit the program if input is invalid

# Add print statement to see what value is being assigned to 'length'
print("Length:", length) 

# Same as above, but for width
try:
    width = int(input("Enter width: "))
    # Check if width is a positive number
    if width <= 0:
        print("Please enter a positive number for width.")
        exit() # Exit the program if input is invalid
except ValueError:
    print("Please enter a valid number for width.")
    exit() # Exit the program if input is invalid

# Add another print statement to see what value is being assigned to 'width'
print("Width:", width) 

# Calculate the area by multiplying length and width
area = length * width 

# Print out the result
print("The area of your rectangle is:", area) 

# Now, the code is more robust and can handle potential errors or incorrect user input. 
# By adding annotations, we can easily understand the purpose of each code segment.

Now, when you run this code, it will output:

// This script prompts the user to enter the length and width of a rectangle and calculates its area.

// Prompt user to enter length
let length = prompt("Enter length: ");

// Convert input to a number
length = Number(length);

// Check if length is a valid number
if (isNaN(length) || length <= 0) {
  // If not, set length to 0
  length = 0;
}

// Print length
console.log("Length: " + length);

// Prompt user to enter width
let width = prompt("Enter width: ");

// Convert input to a number
width = Number(width);

// Check if width is a valid number
if (isNaN(width) || width <= 0) {
  // If not, set width to 0
  width = 0;
}

// Print width
console.log("Width: " + width);

// Calculate area
let area = length * width;

// Print area
console.log("The area of your rectangle is: " + area);

As you can see, the user input for ‘length’ was indeed zero. This helps us identify where the issue lies and allows us to fix it (either by adding a check for negative or zero values, or by providing more specific instructions to the user).

Another useful debugging technique is using breakpoints in your code. This involves setting a temporary stop point that will pause execution at a certain line of code. You can then inspect variables and step through the code line-by-line to see what’s going on.

To set a breakpoint, simply add a # symbol followed by a space before the line number you want to halt execution:

# This code calculates the area of a rectangle based on user input
# Prompt user for input and convert it to an integer
length = int(input("Enter length: ")) 
# Add print statement to see what value is being assigned to 'length'
print("Length:", length) 
# Same as above, but for width
width = int(input("Enter width: ")) 
# Set a breakpoint at line 10 (where we calculate the area) by adding '#' before it
# Calculate the area by multiplying length and width
area = length * width 
# Print out the result
print("The area of your rectangle is:", area) 

# The purpose of this code is to calculate the area of a rectangle based on user input.
# The first two lines prompt the user for input and convert it to an integer.
# The next two lines print out the values of length and width for the user to see.
# The following line calculates the area by multiplying length and width.
# Finally, the last line prints out the result for the user to see.

When you run this code, it will pause execution at line 10 (where we calculate the area). You can then use the ‘up’ arrow key to step through each line of code one-by-one and inspect variables as needed. This is especially useful for complex logic issues where print statements alone may not be enough to identify the problem.

I hope this helps clarify some common debugging techniques in Python! Remember, practice makes perfect keep experimenting with different approaches until you find what works best for you.

SICORPS