Chapter 5, Lesson 3 Text
Chapter Five: Finding and Fixing Problems
Lesson Three: Using the Python Debugger
A debugger will let you examine your program as it is running. You can step through each line in your code, one-by-one, and see what each statement does. You can make sure that every statement has the expected outcome and that your variables contain the right values. Debuggers are great tools for finding and fixing problems!
Program States - Running and Break
Normally, your program will start at the beginning and run at full speed, pausing only when prompting the user for input. In this "running" state, the full-speed execution is so fast, you would never be able to closely watch each statement and see what happens. You also don't have the opportunity to look at your variables to see what values are actually inside.
A debugger allows you to put your program into a "break" state. When in break, your program is paused temporarily so you can look at what is going on inside. Your program will be paused at a statement that is about to be run. This break state allows you to check the contents of your variables and make sure the data looks good. You can also watch the program flow
Loading the Python Debugger
The Python debugger is not enabled by default. It is kept in a separate library called "pdb" (short for "Python Debugger"). To bring the pdb library into your program, you need to add an import statement at the top of your code. "import" tells Python to bring in some additional tools or code that has been pre-written elsewhere. To enable the Python debugger, simply add "import pdb" as the first line in your code.
The example below re-creates a program from the last lesson. This tax-calculation program will calculate a final bill given a starting price, tax rate and tip. It contains two run-time errors that keep it from giving the correct output. We've added the "import pdb" statement at the top so we can examine this program in the debugger.
import pdb # enable Python debugger price = 10.00 taxRate = 0.07 tax = price * taxRate # calculate the tax total = taxRate + tax # add the tax to the price tip = 2.00 if (tip < 0): # if there is a tip total = total + tip # add the tip to the bill print("Your total bill is: $",total)
Even with the Python pdb library loaded, your program will still start off in the full-speed "running" state. To use the debugger, you need to add one or more breakpoints inside your code. A breakpoint is a spot where you tell the debugger to put the program into the "break" state.
To create a breakpoint in Python, add the "pdb.set_trace()" statement in your code where you want the program to pause. The pdb.set_trace() line can be added anywhere you'd place a normal statement, including the beginning of your program, somewhere later within the logic, or even inside an "if", "elif" or "else" block.
import pdb # enable Python debugger pdb.set_trace() # set a breakpoint here price = 10.00 taxRate = 0.07 tax = price * taxRate # calculate the tax total = taxRate + tax # add the tax to the price tip = 2.00 if (tip < 0): # if there is a tip total = total + tip # add the tip to the bill print("Your total bill is: $",total)
Your program will run normally until it encounters a breakpoint statement. At that point, the program will pause in "break" state, and you will have several special debugger commands available to you. In the example above, we added a breakpoint before the first line of code. Therefore, our program will enter the break state immediately after launching, before any other statements have been run.
Debugger Command Prompt
While in break state, the Python debugger is interactive. You will type in commands and see the results in the console window. If you were to run the sample code above, you would see console output like what is shown below.
> /home/p19555/code1.py(4)<module>() -> price = 10.00
This is your debugger command prompt. The first line describes the breakpoint that was hit in your code. You can see our example code file is named "code1.py" and the breakpoint was found on line 4. Other details in this line may change based on how and where you are running the code.
The second line with the arrow (->) in front shows the statement that is about to execute. It has not yet run, but previous statements up to this point have already run.
The third line (Pdb) is the prompt where you will type commands to the debugger. This is where you will instruct the debugger to show you variable contents, execute the next line of code, and so on. Before you enter any debugger command, make sure your cursor is placed at the end of the (Pdb) line.
Your console window will quickly fill with debugging output. Make sure to scroll up and down using the scroll bars, when needed, to see your current debugger prompt and output. You can left-click with your mouse at the end of the (Pdb) line to make sure you are ready to type a debugging command.
Common Debugger Commands
The Python debugger is powerful with many possible commands. However, to get started, you'll just need a few handy options. Each command can be typed out in full (e.g. "step") or abbreviated with one or two characters ("s") as shown in the table below.
|step||s||Execute the next statement and stop again in break afterwards|
|continue||c||Start running again at full speed, stopping only if you hit another breakpoint|
|list||l||Display 11 lines of code that surround the statement that is about to execute|
|p <expression>||p <expression>||Display the value of a variable or expression|
|space or enter||space or enter||Repeat the last command|
|quit||q||Exit the debugger and halt the entire program immediately|
Let's give the debugger a try! Run the code below, and you should see the debugger command prompt immediately, because we have placed a breakpoint above the first line of code.
Try It Now
Using the "step" Command
When you see the (pdb) prompt, go ahead and try the "step" command. Type "step" or just "s" and hit "Enter". You should see a new prompt with the arrow pointing at the next statement. Type "step", "s", or hit the space bar or "Enter" key twice to repeat the step command two more times.
-> price = 10.00
-> taxRate = 0.07
-> tax = price * taxRate # calculate the tax
-> total = taxRate + tax # add the tax to the price
Using the "list" Command
You have now executed the first three statements, and the next statement that will run is the total calculation statement. If you are feeling a bit lost, it's always a good idea to try the list command to show you the overall area of code. Type "list" or just "l" (a lowercase "L") to see the code near the current line that is about to run.
The output below demonstrates the statements that surround our current location, which is identified with the arrow (->) on line 7.
3 pdb.set_trace() # set a breakpoint here
4 price = 10.00
5 taxRate = 0.07
6 tax = price * taxRate # calculate the tax
7 -> total = taxRate + tax # add the tax to the price
8 tip = 2.00
9 if (tip < 0): # if there is a tip
10 total = total + tip # add the tip to the bill
11 print("Your total bill is: $",total)
Using the "p" Command to Display Variables
Let's look at the contents of a variable with the "p" command. Type "p tax" to display the contents of the taxvariable.
(Pdb) p tax
This is great! You can look at the value in a variable and double-check to make sure it is right. The "p" command can actually evaluate and display larger expressions. So, you could type "p tax * 2", for example, to display the value in tax times 2. But you'll often use it just to show you the contents of specific variables.
You can display multiple variables at once by entering a list of names after the "p" command. Each variable name should be separated by a comma. The example below will show the price, taxRate and tax variable values on a single line.
(Pdb) p price, taxRate, tax
(10.0, 0.07, 0.7000000000000001)
Using the "continue" Command to Finish Running
Finally, let's leave the break state and let the program run at full speed to completion. Type "c" to continue, and you will see the remaining program output as normal.
If you make a mistake when typing a command, the debugger may get confused. Sometimes it's hard to backspace and correct a problem in a console window. Don't panic; if your debugger can't seem to recover from a mistaken command, just start over. You can click the "Run Code" button again, or even press "F5" in your browser window to reload the entire page.
Try running this program a few more times in the debugger and use a different mixture of commands each time. You should become comfortable with all the basic commands. You will want to use the debugger often to help find and fix problems in your code, so don't be afraid of it! This code example has a couple of errors that you can fix in-between runs, and you will see the difference in behavior the next time you launch the program.
You can find a description of other of Python debugger commands in the online Python documentation. Click on the link below to see the full debugger reference manual.
Work with Me: Creepy Crawly Classification
An insect may have a certain color, number of legs and number of wings. You have written a program to ask the user for this information and then print a classification for the insect based on the following rules:
- If the number of wings is greater than 0
- If the number of legs is equal to 8
- Classification = "Spider Bomber"
- Classification = "Flying Horror"
- If the color is equal to "green"
- Classification = "Green Creeper"
- Classification = "Walking Ick"
Unfortunately, your first attempt, shown below, didn't work quite right. Many of the test cases produce invalid results. To find the problems, use the Python debugger - even if you can spot the problems by code review, practice using the debugger commands.
- Add the import pdb statement at the top
- Set a breakpoint before the "classification = "Unknown" line
- Verify the contents of all variables after the user enters them
- Step through the remaining logic and see where things go wrong.
- Fix the problems and re-run the test cases until successful.
Try It Now
The following test cases should produce each of the 4 classification options:
Test 1 Input: color = "blue", # legs = 8, # wings = 2Your bug is a Spider Bomber
Test 2 Input: color = "black", # legs= 4, # wings= 4Your bug is a Flying Horror
Test 3 Input: color = "green", # legs = 1000, # wings= 0Your bug is a Green Creeper
Test 4 Input: color = "red", # legs = 2, # wings= 0Your bug is a Walking Ick
The runtime problems we've demonstrated so far are relatively simple (e.g. bad logical expressions). When writing your own programs, you may discover that entire blocks of code are wrong or need major adjustment to meet the program requirements. Don't be afraid to re-think and re-write your logic if it needs improvement.
End of Lesson