Dealing with the imperfect
...or how to handle errors
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: "))</source>
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():
try:
epact()
except ValueError:
print "Error. Please enter an integer value."
year = 0
epact()
except NameError:
print "Error. Please enter an integer value."
year = 0
epact()
except SyntaxError:
print "Error. Please enter an integer value."
year = 0
epact()
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." The interpreter then goes to the 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.
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 epact() function, 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.
In the case of the program above, our exception handlers serve as a type of recursion or loop. When we raise an exception that is handled, the statements underneath our handlers take us back to the beginning of the epact function. This forces the user to keep entering a value, until a valid numeric value is entered. This means our finally statement won't execute until a valid value is entered, because the except statements send us back tot he beginning of the function, which makes it possible to raise yet another exception, which will be handled, and will send us back to the beginning and...well, you get the idea.
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
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
I feel really happy to have seen your webpage and look forward to so many more entertaining times reading here. Thanks once more for all the details.
ReplyDeletepython training in bangalore|
Brilliant caption dude.So clever topic u have chosen and have delivered content in very simple way.Its very clear to understand.
ReplyDeletebest mobile service center in chennai
mobile service center in velachery
mobile service center in vadapalani
mobile service center in porur
best mobile service center