Arrrgh! Why Doesn’t My Python Program Work?

I’m having trouble with a tutorial… it doesn’t work!

I can’t figure out why my code isn’t working!

You’ve been banding your head against your desk for hours. The examples seemed so clear, but when you wrote your program it all fell apart. You’ve looked over the code, again and again. Everything looksfine. IT. JUST. DOESN’T. WORK.

You want your program to work correctly. You want to move past this annoying bug. You want to move on and keep learning. What can you do?

You can do a few things when you are stuck. You can write tests while while you write the program. You can talk to someone (or yourself!) else and get their help.

The Solution!

Use a debugger. A debugger allows you to interactively run a program and check the process state. Use a debugger to quickly explore how a program actually works. A debugger helps you understand Python better than passively reading example programs.

A Detailed Walkthrough

In this case, we will use the built-in Python debugger. The Python program we’re running is from a Reddit post, and the code is here.

First, in your console, start your program (we’re using Python 3.6 at the moment):

This starts the Python interpreter and loads the pdb (the Python debugger) module.

You’ll see the pdb prompt:

This shows you that the program execution starts at the main function definition.

The debugger accepts a number of different commands. The first one we’ll use is the w command – which stands for where, and it will show you the current “line” in the program the debugger is about to execute. It also shows you the current “stack”, or the history of functions the interpreter executed in the program.

(Pdb) w c:\program files\python36\lib\bdb.py(431)run() -> exec(cmd, globals, locals) (1)() > c:\users\jjeffers\pydebug\guesser.py(1)() -> def main():

(Pdb)

The bottom most function is the current executing “frame” of the program.

To get to the next line of the program (and have Python execute the current line), press n (or next).

> if __name__ == “__main__”:
(Pdb)

Notice how the function definition was “skipped”, and the debugger jumped to the next executable line.

Enter n again.

Now we’re entered the if statement, because the test for

was true. The debugger is showing you that the next line to execute is the call to the “main” function.

Enter s (or step) here. The step command works like next, but instructs the debugger to “step into” any function calls.

Don’t worry, we’re not caught in a loop here. Enter n to move to the next line inside the main function.

-> print(“Guess a number between 1 and 100.”)
(Pdb)

Keep using n until you reach the line:

-< while not found:
(Pdb)

You will see the lines for the variable definitions for found and randomNumber. You can use the debugger to query the interpreter for the current value of a variable.

Let’s move on until you get to the prompt:

-> userGuess = input(“Your Guess: “)
(Pdb)

Enter n again, then and enter 3 when prompted.

The very next line is

-> if userGuess == randomNumber:
(Pdb)

Here’s where the debugger really gets useful. Go ahead and query the test expression:

(Pdb) userGuess == randomNumber
False

This shows you where the issue is, but it might still not be clear why that test fails until we look at the operands userGuess and randomNumber.

(Pdb) userGuess ‘3’ (Pdb) randomNumber

3

And that’s it – the 2 variables hold different values – one is a string and the other is an integer.

Using the debugger is a good skill to learn. It helps you track down issues in a running program. If you want to add more safety, you need to write tests, too.

If you want a detailed example of writing a test, check out Keep Calm and Add Unit Tests with Python.

View all posts by James Jeffers

Published March 5, 2018February 1, 2019