Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions

  




 

 

Basic Exception Handling

Exception handling is done with the try statement. The try statement encapsulates several pieces of information. Primarily, it contains a suite of statements and a group of exception-handling clauses. Each exception-handling clause names a class of exceptions and provides a suite of statements to execute in response to that exception.

The basic form of a try statement looks like this:

try: suite

except exception 〈, target 〉 : suite

except: suite

Each suite is an indented block of statements. Any statement is allowed in the suite. While this means that you can have nested try statements, that is rarely necessary, since you can have an unlimited number of except clauses.

If any of the statements in the try suite raise an exception, each of the except clauses are examined to locate a clause that matches the exception raised. If no statement in the try suite raises an exception, the except clauses are silently ignored.

The first form of the except clause provides a specific exception class which is used for matching any exception which might be raised. If a target variable name is provided, this variable will have the exception object assigned to it.

The second form of the except clause is the "catch-all" version. This will match all exceptions. If used, this must be provided last, since it will always match the raised exception.

We'll look at the additional finally clause in a later sections.

The structure of the complete try statement summarizes the philosophy of exceptions. First, try the suite of statements, expecting them work. In the unlikely event that an exception is raised, find an exception clause and execute that exception clause suite to recover from or work around the exceptional situation.

Except clauses include some combination of error reporting, recovery or work-around. For example, a recovery-oriented except clause could delete useless files. A work-around exception clause could returning a complex result for square root of a negative number.

First Example. Here's the first of several related examples. This will handle two kinds of exceptions, ZeroDivisionError and ValueError.

Example 17.1. exception1.py

def avg( someList ):
    """Raises TypeError or ZeroDivisionError exceptions."""
    sum= 0
    for v in someList:
        sum = sum + v
    return float(sum)/len(someList)

def avgReport( someList ):
    try:
        m= avg(someList)
        print "Average+15%=", m*1.15
    except TypeError, ex:
        print "TypeError: ", ex
    except ZeroDivisionError, ex:
        print "ZeroDivisionError: ", ex

This example shows the avgReport function; it contains a try clause that evaluates the avg function. We expect that there will be a ZeroDivisionError exception if an empty list is provided to avg. Also, a TypeError exception will be raised if the list has any non-numeric value. Otherwise, it prints the average of the values in the list.

In the try suite, we print the average. For certain kinds of inappropriate input, we will print the exceptions which were raised.

This design is generally how exception processing is handled. We have a relatively simple, clear function which attempts to do the job in a simple and clear way. We have a application-specific process which handles exceptions in a way that's appropriate to the overall application.

Nested try Statements. In more complex programs, you may have many function definitions. If more than one function haa a try statement, the nested function evaluations will effectively nest the try statements inside each other.

This example shows a function solve, which calls another function, quad. Both of these functions have a try statement. An exception raised by quad could wind up in an exception handler in solve.

Example 17.2. exception2.py

def sum( someList ):
    """Raises TypeError"""
    sum= 0
    for v in someList:
        sum = sum + v
    return sum

def avg( someList ):
    """Raises TypeError or ZeroDivisionError exceptions."""
    try:
        s= sum(someList)
        return float(s)/len(someList)
    except TypeError, ex:
        return "Non-Numeric Data"

def avgReport( someList ):
    try:
        m= avg(someList)
        print "Average+15%=", m*1.15
    except TypeError, ex:
        print "TypeError: ", ex
    except ZeroDivisionError, ex:
        print "ZeroDivisionError: ", ex

In this example, we have the same avgReport function, which uses avg to compute an average of a list. We've rewritten the avg function to depend on a sum function. Both avgReport and avg contain try statements. This creates a nested context for evaluation of exceptions.

Specifically, when the function sum is being evaluated, an exception will be examined by avg first, then examined by avgReport. For example, if sum raises a TypeError exception, it will be handled by avg; the avgReport function will not see the TypeError exception.

Function Design - Exceptions or Status Codes. Note that this example has a subtle bug that illustrates an important point regarding function design. We introduced the bug when we defined avg to return either an answer or an error status code in the form of a string. Generally, things are more complex when we try to mix valid results and error codes.

Status codes are the only way to report errors in languages that lack exceptions. C, for example, makes heavy use of status codes. The POSIX standard API definitions for operating system services are oriented toward C. A program making OS requests must examing the results to see if it is a proper values or an indication that an error occurred. Python, however, doesn't have this limitation. Consequently many of the OS functions available in Python modules will raise exceptions rather than mix proper return values with status code values.

In our case, our design for avg attepts to return either a valid numeric result or a string result. To be correct we would ave to do two kinds of error checking in avgReport. We would have to handle any exceptions and we would also have to examine the results of avg to see if they are an error value or a proper answer.

Rather than return status codes, a better design is to simply use exceptions for all kinds of errors. IStatus codes have no real purposes in well-designed programs. In the next section, we'll look at how to define and raise our own exceptions.


 
 
  Published under the terms of the Open Publication License Design by Interspire