Python supports special statements to enable error handling. The key
structure is the try ...except... block:
try:
# statements to try go here
except:
# code to handle exceptions (errors) goes here
A try statement works a bit like an if statement.
First the statements inside the try block are executed. If they all complete
without an error (exception) occurring the except block is skipped. However if an exception is generated by any of the statements in the try block, then the remaining statements in the try block are
skipped and Python looks for an except clause that handles that
particular exception. Simple example:
try:
x = int(raw_input("Please enter an integer value: "))
except ValueError:
print "Give me an integer damnit!"
If I run it,
Please enter an integer value: hello Give me an integer damnit!
And here it is dressed up a bit,
done = False
while not done:
try:
x = int(raw_input('Please enter an integer value: '))
done = True
except ValueError:
print 'Give me an integer damnit!'
print 'Thanks!'
and its output when run (by an idiot),
>>> Please enter an integer value: hello Give me an integer damnit! Please enter an integer value: 4.5 Give me an integer damnit! Please enter an integer value: 3 Thanks! >>>
Now how did I know to watch for a ValueError exception in that
code? Because I'd seen it when running the code without exception handling:
>>> x = int(raw_input('Please enter an integer value: '))
Please enter an integer value: 4.5
Traceback (most recent call last):
File "< pyshell#22>", line 1, in < module>
x = int(raw_input('Please enter an integer value: '))
ValueError: invalid literal for int() with base 10: '4.5'
>>>
We've seen lots of error messages during CPSC 128 and CPSC 129, but perhaps never realized that every one of them was telling us what exception we'd caused! Instead of nagging us, Python was reaching out to us and offering us a handle to deal with the problem we had (inadvertently) caused. Some more examples:
>>> 'tim'.sort()
Traceback (most recent call last):
File "< pyshell#26>", line 1, in < module>
'tim'.sort()
AttributeError: 'str' object has no attribute 'sort'
>>> 10/0
Traceback (most recent call last):
File "< pyshell#27>", line 1, in < module>
10/0
ZeroDivisionError: integer division or modulo by zero
>>> '1' + 1
Traceback (most recent call last):
File "< pyshell#28>", line 1, in < module>
'1' + 1
TypeError: cannot concatenate 'str' and 'int' objects
>>>
The Python documentation provides a complete list of built-in exceptions.
Back to try...except... syntax. Most try blocks will contain a
few statements, several of which may be able to generate exceptions (and some
of which may be capable of generating more than one). You can have as many except clauses as you need to catch and handle the errors you can
recover from,
>>> b = 0
>>> try:
print a/b
except NameError:
print 'Either a or b, or both, don\'t exist.'
except ZeroDivisionError:
print 'Dang, b must be 0.'
Either a or b, or both, don't exist.
>>> a = 5
>>> try:
print a/b
except NameError:
print 'Either a or b, or both, don\'t exist.'
except ZeroDivisionError:
print 'Dang, b must be 0.'
Dang, b must be 0.
>>>
There is much more that can be learned about exceptions:
Exceptions are first class objects, i.e. they are members of classes and can have both data (attributes) and methods.
If there is no handler for an exception in the block where the
exception occurred it will be passed to try statements in
enclosing blocks.
You aren't limited to using only the built-in exceptions, you can create, raise and handle your own exceptions that are specific to the kind of processing your program is doing.
The Python tutorial provides a more gradual introduction to these advanced aspects of exceptions than the reference manual if you are interested, but we will not make use of them in CPSC 129.