Go to top, next, previous, or johnstachurski.net

Handling Exceptions

Runtime errors cause execution of the relevant program to stop

A better way is to add code to your program that deals with errors as they occur

Errors

If you've got this far then you've already seen lots of errors

Here's an example:

>>> def f:
  File "<stdin>", line 1
    def f:
         ^
SyntaxError: invalid syntax

This is a syntax error

Here's a different kind of error, unrelated to syntax:

>>> 1 / 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero

Here's another:

>>> x = y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined

And another:

>>> 'foo' + 6
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects

And another:

>>> X = []
>>> x = X[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

On each occaision, the interpreter informs us of the error type

In Python, these errors are called exceptions

We can catch and deal with exceptions using try-except blocks

Here's a simple example

def f(x):
    try:
        return 1.0 / x 
    except ZeroDivisionError:
        print 'Error: division by zero.  Returned None'
    return None

When we call f we get the following output

>>> f(2)
0.5
>>> f(0)
Error: division by zero.  Returned None
>>> f(0.0)
Error: division by zero.  Returned None
>>> 

The error is caught and execution of the program is not terminated

Note that other error types are not caught

If we are worried the user might pass in a string, we can catch that error too

def f(x):
    try:
        return 1.0 / x 
    except ZeroDivisionError:
        print 'Error: Division by zero.  Returned None'
    except TypeError:
        print 'Error: Unsupported operation.  Returned None'
    return None

Here's what happens

>>> f(2)
0.5
>>> f(0)
Error: Division by zero.  Returned None
>>> f('foo')
Error: Unsupported operation.  Returned None
>>> 

If we feel lazy we can catch these errors together

def f(x):
    try:
        return 1.0 / x 
    except (TypeError, ZeroDivisionError):
        print 'Error: Unsupported operation.  Returned None'
    return None

Here's what happens

>>> f(2)
0.5
>>> f(0)
Error: Unsupported operation.  Returned None
>>> f('foo')
Error: Unsupported operation.  Returned None

If we feel extra lazy we can catch all error types as follows

def f(x):
    try:
        return 1.0 / x 
    except:
        print 'Error.  Returned None'
    return None

In general it's better to be specific

Problem:

Suppose we have a text file numbers.txt containing

prices
3
8

7
21

Using try-except, write a program to read in the contents of the file and sum the numbers, ignoring lines without numbers

Solution:

f = open('numbers.txt')

total = 0.0 
for line in f:
    try:
        total += float(line)
    except ValueError:
        pass

f.close()

print total