Exceptions

Errors in Python can be separated into syntax errors and runtime errors. Syntax errors are caused by eg. unpaired brackets, wrong indentation, etc. A program with syntax errors can not run at all. More frequent are run-time errors that arise from an improper use of a function, missing data, etc. Since Python is an interpreted, dynamically typed language, most errors will show up on the fly, as opposed to compiled languages, where many errors occur during compilation.

Exceptions

Exception is thrown when an error occurs. If we miss this exception (see below), the program interrupted. E.g. division by zero throws an ZeroDivisionError exception.

In [1]:
1/0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-1-05c9758a9c21> in <module>()
----> 1 1/0

ZeroDivisionError: division by zero

Catching exceptions

If you do not want to interrupt the program at the moment of an exception, we can use a try - except block. It works so that the unsafe part of the code is placed under try, followed by an except block, which contains instructions in the case of an error (exception).

In [2]:
try:
    1/0
except:
    print("Don't divide by zero!")
Don't divide by zero!

except used as above catches all exceptions. This is not usually a good practice. It is advised to catch only specific exceptions (those that are expected). To catch the division by zero one would write:

In [3]:
try:
    1/0
# the e variable will contain the exception
except ZeroDivisionError as e:
    print("Don't divide by zero!")
    print(e)
Don't divide by zero!
division by zero

Complete try-except block may also contain else and finally blocks, see documentation . finally is especially useful for "cleaning", eg. to close a file etc.

Raising exceptions

Exceptions can, of course, be also thrown in our code using the raise keyword. For example, checking the input of a function can be carried out like this:

In [4]:
def fact(n):
    """Calculates the factorial
    """
    from math import factorial
    try:
        # try to convert n to a number
        n = float(n)
    except ValueError as e:
        raise ValueError('{} is not a number'.format(repr(n)))
    # is n integer >= 0
    if not n.is_integer() or n < 0:
        raise ValueError("{} is not an integer >= 0".format(n))
    return factorial(n)

# let's test the function
n = 4
print('{}! = {}'.format(n, fact(n)))
4! = 24
In [5]:
# do the exeptions work?
for n in (4.0, "0", "zero", 3.2, -1):
    try:
        print('{}! = {}'.format(n, fact(n)))
    # the Exception class covers almost any exception
    except Exception as e:
        print(e)
4.0! = 24
0! = 1
'zero' is not a number
3.2 is not an integer >= 0
-1.0 is not an integer >= 0

Traceback

The traceback module provides means to discover the exception origin. Let's demonstrate the print_exc function:

In [6]:
import traceback, sys

try:
    fact(1.1)
except Exception:
    traceback.print_exc(file=sys.stdout)
Traceback (most recent call last):
  File "<ipython-input-6-4cdf470d9bc2>", line 4, in <module>
    fact(1.1)
  File "<ipython-input-4-35a894deb88d>", line 12, in fact
    raise ValueError("{} is not an integer >= 0".format(n))
ValueError: 1.1 is not an integer >= 0

Comments

Comments powered by Disqus