🔍 Debugging Code

Debugging is the process of finding and fixing bugs in your code. Python provides several tools and techniques to help you identify issues and understand how your code behaves.

# Simple debugging with print statements
def calculate_average(numbers):
    print(f"Input numbers: {numbers}")  # Debug output
    total = sum(numbers)
    print(f"Total sum: {total}")        # Debug output
    average = total / len(numbers)
    print(f"Average: {average}")        # Debug output
    return average

result = calculate_average([10, 20, 30])
print(f"Final result: {result}")

🎯 Basic Debugging Techniques

Start with simple debugging methods that require no special tools.

# Debug with print statements
def find_maximum(numbers):
    print(f"Starting with numbers: {numbers}")
    
    if not numbers:
        print("List is empty!")
        return None
    
    max_value = numbers[0]
    print(f"Initial max_value: {max_value}")
    
    for i, num in enumerate(numbers[1:], 1):
        print(f"Comparing {max_value} with {num} at index {i}")
        if num > max_value:
            max_value = num
            print(f"New max_value: {max_value}")
    
    print(f"Final maximum: {max_value}")
    return max_value

# Test the function
result = find_maximum([3, 7, 2, 9, 1])

Variable Inspection

# Inspect variables at different points
def process_text(text):
    print(f"Original text: '{text}'")
    print(f"Text type: {type(text)}")
    print(f"Text length: {len(text)}")
    
    # Process the text
    cleaned = text.strip().lower()
    print(f"After cleaning: '{cleaned}'")
    
    words = cleaned.split()
    print(f"Words: {words}")
    print(f"Word count: {len(words)}")
    
    return words

words = process_text("  Hello World Python  ")

Debug Function Calls

# Track function execution
def debug_function_call(func_name, *args, **kwargs):
    print(f"Calling {func_name} with args={args}, kwargs={kwargs}")

def add_numbers(a, b):
    debug_function_call("add_numbers", a, b)
    result = a + b
    print(f"add_numbers returning: {result}")
    return result

def multiply_numbers(a, b):
    debug_function_call("multiply_numbers", a, b)
    result = a * b
    print(f"multiply_numbers returning: {result}")
    return result

# Test functions
sum_result = add_numbers(5, 3)
product_result = multiply_numbers(4, 6)

🐛 Python Debugger (pdb)

The Python debugger allows you to step through code line by line.

Basic Debugger Commands

CommandShortcutPurpose
continuecContinue execution
stepsStep into functions
nextnNext line (don't step into)
listlShow current code
printpPrint variable value
quitqQuit debugger

Using the Debugger

import pdb

def buggy_function(numbers):
    total = 0
    for i in range(len(numbers)):
        pdb.set_trace()  # Start debugger here
        total += numbers[i]
    return total

# When this runs, debugger will activate
# Use 'n' to step through, 'p total' to print total
# Use 'c' to continue, 'q' to quit
result = buggy_function([1, 2, 3, 4])

Conditional Breakpoints

import pdb

def process_items(items):
    for i, item in enumerate(items):
        # Only break on specific condition
        if item < 0:
            pdb.set_trace()  # Debug negative values
        
        processed = item * 2
        print(f"Item {i}: {item} -> {processed}")

# Test with mixed values
process_items([5, -2, 8, -1, 3])

📋 Debugging Strategies

StrategyWhen to UseExample
Print debuggingSimple issuesprint(f"x = {x}")
Rubber duckLogic problemsExplain code to someone
Binary searchLarge codebaseComment out half the code
Minimal exampleComplex bugsRecreate with simple code

🔧 Common Debugging Scenarios

Index and Range Errors

def safe_list_access(items, index):
    print(f"Accessing index {index} in list of length {len(items)}")
    print(f"List contents: {items}")
    
    if index < 0:
        print(f"Negative index: {index}")
        return None
    
    if index >= len(items):
        print(f"Index {index} out of range (max: {len(items)-1})")
        return None
    
    value = items[index]
    print(f"Found value: {value}")
    return value

# Test edge cases
test_list = [10, 20, 30]
safe_list_access(test_list, 5)  # Out of range
safe_list_access(test_list, -1) # Negative
safe_list_access(test_list, 1)  # Valid

Type and Value Errors

def debug_calculations(a, b):
    print(f"Input a: {a} (type: {type(a)})")
    print(f"Input b: {b} (type: {type(b)})")
    
    # Check if inputs are numbers
    if not isinstance(a, (int, float)):
        print(f"Error: 'a' is not a number")
        return None
    
    if not isinstance(b, (int, float)):
        print(f"Error: 'b' is not a number")
        return None
    
    # Check for division by zero
    if b == 0:
        print("Error: Cannot divide by zero")
        return None
    
    result = a / b
    print(f"Result: {a} / {b} = {result}")
    return result

# Test with different inputs
debug_calculations(10, 2)      # Valid
debug_calculations("10", 2)    # Type error
debug_calculations(10, 0)      # Division by zero

Logic Error Detection

def find_even_numbers(numbers):
    even_numbers = []
    
    print(f"Looking for even numbers in: {numbers}")
    
    for i, num in enumerate(numbers):
        print(f"Checking number {num} at index {i}")
        
        if num % 2 == 0:
            print(f"  {num} is even - adding to list")
            even_numbers.append(num)
        else:
            print(f"  {num} is odd - skipping")
    
    print(f"Final even numbers: {even_numbers}")
    return even_numbers

# Test the function
result = find_even_numbers([1, 2, 3, 4, 5, 6])

📊 Debug Information Reference

Useful Built-in Functions for Debugging

FunctionPurposeExample
type()Get object typetype(variable)
len()Get lengthlen(list)
dir()List object attributesdir(object)
vars()Get object variablesvars(object)
id()Get object IDid(variable)
repr()Get string representationrepr(object)

Error Information

AttributePurposeExample
__class__Exception classe.__class__.__name__
argsException argumentse.args
__traceback__Traceback objecte.__traceback__

🎯 Key Takeaways

🚀 What's Next?

Learn how to implement proper logging for tracking application behavior and errors.

Continue to: Use Logging

Was this helpful?

😔Poor
🙁Fair
😊Good
😄Great
🤩Excellent