Kahibaro
Discord Login Register

Debugging strategies

What “Debugging” Really Means in Practice

Debugging is the process of finding and fixing the cause of a problem (a bug) in your code. In this chapter, you’ll focus on how to do that effectively.

You already know that errors happen and that Python shows error messages. Debugging strategies are about what you actually do once you notice something is wrong—whether it’s an error message or just wrong behavior.

This chapter is practical: step‑by‑step methods, habits, and tools you can use every day.


1. Start With a Clear Problem Statement

Before you dive into the code, be very clear:

Write this down in plain language. For example:

Having a clear “expected vs actual” description stops you from randomly changing code.


2. Reproduce the Bug Consistently

You can’t fix what you can’t reproduce.

Examples:

Once you have steps to reliably trigger the bug, debugging becomes much easier.


3. Read Error Messages Systematically

Error messages were introduced earlier; here’s a simple strategy to use them:

  1. Look at the last line of the error.
    • It tells you the error type (like ValueError, IndexError).
  2. Look at the line number and file name just above.
  3. Read the short description on the last line in plain language.

Example:

ValueError: invalid literal for int() with base 10: 'abc'

Strategy:

Don’t just skim error messages; treat them as clues.


4. Add Temporary Print Statements

One of the simplest and most powerful debugging tools is print().

You can:

Example:

age = input("Enter your age: ")
print("DEBUG: raw age input =", age)  # temporary debug print
age_num = int(age)
print("DEBUG: converted age =", age_num)

Use these to answer:

When you’re done, delete or comment out debugging prints.


5. Debugging by Simplifying (Narrowing Down)

If your program is long, don’t try to fix everything at once. Instead, isolate the problem.

Strategies:

  1. Comment out large sections of code.
    • Run only a small part at a time.
    • If the bug disappears, the problem is in the commented-out part.
  2. Replace complex code with a simpler version to test ideas.

Example: If a long function is failing:

def calculate_bill(items):
    # Temporarily simplify to see if the problem is inside this function
    print("DEBUG: calculate_bill called with:", items)
    return 0  # placeholder

If the program runs without crashing now, the issue is inside your original function body.


6. Check One Change at a Time

When debugging, change only one thing and then run your code again.

Think of it like a science experiment: one variable at a time.


7. Compare With a Smaller Example

If something is confusing, create a tiny, separate script that only tests the idea you’re unsure about.

Examples:

  print(5 / 2)
  print(5 // 2)

This “toy example” approach helps you understand behavior without distractions.


8. Trace the Code Step by Step (Mentally or on Paper)

Walk through the code line by line as if you were the computer.

For each line:

You can do this:

Example:

Code:

x = 0
for i in range(3):
    x = x + i

Trace table:

Stepix beforex after
1000
2101
3213

If the table doesn’t match what your program prints, you’ve found a misunderstanding.


9. Use the Python Debugger (`pdb`) (Gentle Intro)

For more control than print(), you can use the built-in debugger.

Basic use:

  1. Add this line where you want to pause execution:
   import pdb; pdb.set_trace()
  1. Run your script as usual.
  2. When Python hits that line, it stops and gives you a (Pdb) prompt.

At the (Pdb) prompt, you can:

You don’t need to master pdb now, but knowing it exists is useful for stepping through code line by line.


10. Check Inputs and Assumptions

Often, bugs happen because something you assumed is not true.

Ask questions like:

You can add checks:

if len(numbers) == 0:
    print("DEBUG: numbers list is empty!")

Or:

if age < 0:
    print("DEBUG: negative age detected:", age)

Debugging often means discovering that the real world doesn’t match your assumptions.


11. Use Assertions for Internal Checks

Assertions are a way to say “this must be true here; if not, crash with a clear message.”

Syntax:

assert condition, "Message if condition is False"

Example:

total = sum(prices)
assert total >= 0, "Total price cannot be negative"

If the condition is False, Python raises an AssertionError with your message.

Assertions are especially useful to catch impossible or unexpected states earlier, closer to where they happen.


12. Binary Search Debugging (Divide and Conquer)

For bugs in longer code or data:

  1. Pick the middle point of the code or data.
  2. Add a print() or check there.
  3. See if things are correct up to that point.

Repeat:

This is like searching for a word in a dictionary by always opening in the middle.


13. Read the Code Out Loud (Rubber Duck Debugging)

Explaining your code, even to an object (like a “rubber duck”), often reveals mistakes.

Steps:

  1. Imagine someone knows basic Python but nothing about your code.
  2. Explain:
    • “First, this function does X.”
    • “Then it checks if Y.”
    • “Here I expect Z to happen.”

As you explain, you may notice:

You can also do this with a friend or classmate.


14. Use Version Control (Even in a Simple Way)

You don’t need advanced tools, but you should avoid losing working code.

Strategies:

Then:

Later, you can learn git, but simple copying is already helpful for beginners.


15. Ask for Help Effectively

When you’re really stuck, asking for help is part of debugging.

When you ask, include:

  1. A short description of what you’re trying to do.
  2. What you expected to happen.
  3. What actually happens (including the full error message).
  4. A small code example that shows the problem (not your whole project if possible).
  5. What you already tried.

Example:

Being clear and specific speeds up getting a useful answer and also often helps you see the bug yourself while preparing the question.


16. Develop a Debugging Mindset

Good programmers are not people who never make mistakes; they are people who debug calmly and systematically.

Key attitudes:

Over time, you will:

17. A Simple Debugging Checklist

When you face a bug, you can follow this simple checklist:

  1. Can I reproduce the bug every time?
  2. Did I read the full error message and check the line number?
  3. Did I print variable values around the problem area?
  4. Can I simplify or isolate the issue in a smaller script?
  5. Have I made only one change at a time and tested after each?
  6. Did I walk through the code step by step, maybe on paper?
  7. Have I checked my assumptions about inputs and data?
  8. If I’m still stuck, can I prepare a clear question with a small code example?

Using strategies like these will make debugging less frustrating and much more manageable as your programs grow in size and complexity.

Views: 18

Comments

Please login to add a comment.

Don't have an account? Register now!