06 Prepare: Troubleshooting Functions
What should you do when your program isn’t working? If your program is small, you could examine each line of the program. However, if your program is large or contains multiple functions, there are better ways to find and fix the problems, including writing and running test functions, writing print statements, and using a debugger.
Concepts
Here are the Python programming concepts and topics that you should learn during this lesson.
Types of Mistakes
Broadly speaking, there are two types of mistakes or errors that
a programmer might make when writing a program: syntax errors and
logic errors. A syntax error is a mistake made by a
programmer that violates the rules of a programming language such as
misspelling a keyword, forgetting to type a closing parenthesis, or
forgetting to type a colon (:) at the end of an if
statement. A syntax error will cause the computer to terminate a
Python program and print an error message to the terminal window. A
logic error is a mistake made by a programmer that causes
the computer to produce the wrong results. Often, a logic error will
not cause the computer to terminate a program or to print an error
message. It will simply cause the computer to produce incorrect
results.
Error Messages
Regardless of the type of error (syntax or logic), if the computer prints an error message while executing a program, the first thing a programmer should do is read and understand the error message. Example 1 shows a simple Python program that contains a syntax error. The message that the computer printed because of the syntax error is shown below example 1.
# Example 1 def main(): print("Are you surprised, Clark?) # Start this program by # calling the main function. if __name__ == "__main__": main()
> python surprise.py File "C:\Users\cse111\surprise.py", line 4 print("Are you surprised, Clark?) ^ SyntaxError: EOL while scanning string literal
From the error message, we read that example 1 contains a syntax error and that the error is on line 4 of the program where there is something wrong with the string. By examining the error message and the program at line 4, we learn that the programmer forgot to type the closing double quote at the end of the string. By the way, EOL that appears in the error message is an acronym for "end of line." You might also see the acronyms EOF and EOT which mean "end of file" and "end of transmission."
If the computer prints an error message that you don’t understand, you can search the internet for its meaning. Simply copy and paste the error message into the search bar of your browser. Here are two of the search results from Google for the error message "SyntaxError: EOL while scanning string literal."
Print Statements
If the computer doesn’t print an error message, but your program is producing incorrect results, you could add print statements to your program in strategic locations to help you find the mistakes. These print statements should print the value of the variables in your program so that you can examine the values to ensure they are correct. Example 2 contains a program with a complex calculation for computing the remaining balance of a loan. Notice the print statements at lines 28, 32, and 35 and also at lines 43, 47, and 50. The programmer wrote these print statements at important points in the program, specifically near the beginning of each function and in the middle of the calculations.
# Example 2 def main(): print("This program computes and prints the remaining") print("balance for a loan with a fixed annual percentage") print("rate and a fixed number of payments per year.") print() print("Please enter the following five values.") principal = float(input("Principal amount: ")) annual_rate = float(input("Annual percentage rate: ")) years = int(input("Number of years in the life of the loan: ")) payments_per_year = int(input("Number of payments per year: ")) number_paid = int(input("Number of payments already paid: ")) balance = compute_balance(principal, annual_rate, years, payments_per_year, number_paid) print() print(f"Balance remaining: {balance}") def compute_balance(princ, ar, years, ppy, ptd): """Compute and return the balance remaining for a loan.""" payment = compute_payment(princ, ar, years, ppy) print() print(f"compute_balance({princ}, {ar}, {years}, {ppy}, {ptd})") rate = ar / ppy power = (1 + rate) ** ptd print(f" payment: {payment} rate: {rate} power: {power}") balance = princ * power - payment * (power - 1) / rate print(f" balance: {balance:.2f}") return round(balance, 2) def compute_payment(princ, ar, years, ppy): """Compute and return the payment per period for a loan.""" print() print(f"compute_payment({princ}, {ar}, {years}, {ppy})") rate = ar / ppy n = years * ppy print(f" rate: {rate} n: {n}") payment = princ * rate / (1 - (1 + rate) ** -n) print(f" payment: {payment:.2f}") return round(payment, 2) # Start this program by # calling the main function. if __name__ == "__main__": main()
> python balance.py This program computes and prints the remaining balance for a loan with a fixed annual percentage rate and a fixed number of payments per year. Please enter the following five values. Principal amount: 80000 Annual percentage rate: 0.06 Number of years in the life of the loan: 15 Number of payments per year: 12 Number of payments already paid: 45 compute_payment(80000.0, 0.06, 15, 12) rate: 0.005 n: 180 payment: 675.09 compute_balance(80000.0, 0.06, 15, 12, 45) payment: 675.09 rate: 0.005 power: 1.2516208207696773 balance: 66156.33 Balance remaining: 66156.33
Although print statements are simple to understand and add to a program and often helpful, in many situations they are not the most effective way to find logic errors.
Test Functions
Many programmers underestimate the effectiveness of writing and running test functions to find logic errors in a program. Many programmers will write a complete program with multiple functions and never pause to test any part of it. Instead, they will write the entire program and then do something similar to the following steps to test it.
- Run the program and enter input like a user would.
- Examine the program’s output and discover that the output is incorrect.
- Review all the program’s code, make some small changes, and add print statements.
- Repeat steps 1–3 again and again and again, spending lots of time trying to find and fix the errors.
This method for finding and fixing mistakes is time consuming because the programmer is trying to test the whole program at once. Instead, the programmer should test each individual function by writing and running test functions as explained in the previous lesson.
Using a Debugger
A debugger is a software development tool that allows a programmer to watch the computer execute the statements in a program. While using a debugger, a programmer can examine the values stored in a program’s variables as the computer executes each line of the program. A debugger is a very effective tool for finding mistakes in a program. Nearly all programming languages and environments include a debugger. Professional software developers use a debugger nearly every single work day. Most companies will not use a programming language unless that language includes a debugger.
The Python programming language includes a debugger that you can use while writing a program in VS Code. It is much easier to learn how to use a debugger by watching someone use it than by reading about a debugger. Watch the following video that shows a BYU-Idaho faculty member using a debugger in VS Code to find mistakes in a program.
- How to Use the Python Debugger in VS Code (17 minutes)
A debugger is also a great learning tool. Using a debugger to
step through the statements of your program one at a time and
examining the values of the variables after each step will show you
exactly how Python works. Try it! If you don’t completely understand
if
-elif
-else
statements,
while
loops, for
loops, passing
parameters, or returning a value from a function, then put one or
more breakpoints in a program that contains those elements, start
the program in the debugger, and step through it one line at a time.
After the computer executes each statement, examine the values of
the variables and predict in your mind how the next statement will
change the values of the variables.
Summary
During this lesson, you are learning the difference between a syntax error and a logic error. A syntax error is a mistake made by a programmer that violates the rules of a programming language and prevents a program from running. Usually, you must fix all syntax errors before your program will run. After you fix all syntax errors, your program will run but may contain logic errors. A logic error is a mistake made by a programmer that causes the computer to produce the wrong results. Some tools that you can use to find and fix the logic errors in your programs are test functions, print statements, and a debugger.