Non-Programmer's Tutorial for Python 2.6/Dealing with the imperfect

...or how to handle errors

edit

So you now have the perfect program, it runs flawlessly, except for one detail, it will crash on invalid user input. Have no fear, for Python has a special control structure for you. It's called try and it tries to do something. Here is an example of a program with a problem:

print "Type Control C or -1 to exit"
number = 1
while number != -1:
    number = int(raw_input("Enter a number: "))
    print "You entered:", number

Notice how when you enter @#& it outputs something like:

Traceback (innermost last):
 File "try_less.py", line 4, inĀ ?
    number = int(raw_input("Enter a number: "))</syntaxhighlight>

ValueError: invalid literal for int(): @#&

As you can see the int() function is unhappy with the number @#& (as well it should be). The last line shows what the problem is; Python found a ValueError. How can our program deal with this? What we do is first: put the place where the errors occurs in a try block, and second: tell Python how we want ValueErrors handled. The following program does this:

print "Type Control C or -1 to exit"
number = 1
while number != -1:
    try:
        number = int(raw_input("Enter a number: "))
        print "You entered:", number
    except ValueError:
        print "That was not a number."

Now when we run the new program and give it @#& it tells us "That was not a number." and continues with what it was doing before.

When your program keeps having some error that you know how to handle, put code in a try block, and put the way to handle the error in the except block.

Here is a more complex example of Error Handling.

# Program by Mitchell Aikens 2012
# No copyright.
import math

def main():
	success = 0
	while (success == 0):
		try:
			epact()
			success = 1
		except ValueError:
			print "Error. Please enter an integer value."
			year = 0
		except NameError:
			print "Error. Please enter an integer value."
			year = 0
		except SyntaxError:
			print "Error. Please enter an integer value."
			year = 0
		finally:
			print "Program Complete"

def epact():
    
    year = int(input("What year is it?\n"))
    C = year/100
    epactval = (8 + (C/4) - C + ((8*C + 13)/25) + 11 * (year%19))%30
    print "The Epact is: ",epactval

main()

The program above uses concepts from previous lessons as well as the current lesson. Let's look at the above program in sections.

After we define the function called "main", we tell it that we want to "try" function named "epact". It does so "while" there is no "success". The interpreter then goes to the line year = int(input("What year is it?\n")). The interpreter takes the value entered by the user and stores it in the variable named "year".

If the value entered is not an integer or a floating point number (which would be converted to an integer by the interpreter), an exception would be raised, and execution of the try block ends, just before success is assigned the value 1.

Let's look at some possible exceptions. the program above does not have an except clause for every possible exception, as there are numerous types or exceptions.

If the value entered for year is an alphabetical character, a NameError exception is raised. In the program above, this is caught by the except NameError: line, and the interpreter executes the print statement below the except NameError:, then it sets the value of "year" to 0 as a precaution, clearing it of any non-numeric number. The interpreter then jumps back to the first line of the while loop, and the process restarts.

The process above would be the same for the other exceptions we have. If an exception is raised, and there is an except clause for it in our program, the interpreter will jump to the statements under the appropriate except clause, and execute them.

The finally statement, is sometimes used in exception handling as well. Think of it as the trump card. Statements underneath the finally clause will be executed regardless of if we raise and exception or not. The finally statement will be executed after any try or except clauses prior to it.

Below is a simpler example where we are not looped, and the finally clause is executed regardless of exceptions.

#Program By Mitchell Aikens 2012
#Not copyright.

def main():
    try:
        number = int(input("Please enter a number.\n"))
        half = number/2
        print "Half of the number you entered is ",half
    except NameError:
        print "Error."
    except ValueError:
        print "Error."
    except SyntaxError:
        print "Error."
    finally:
        print "I am executing the finally clause."
        
main()

If we were to enter an alphabetic value for number = int(input("Please enter a number.\n")), the output would be as follows:

Please enter a number.
t
Error.
I am executing the finally clause.

Exercises

edit

Update at least the phone numbers program (in section File IO) so it doesn't crash if a user doesn't enter any data at the menu.