The
raise
statement does two things: it creates
an exception
object, and immediately leaves the
expected program execution sequence to search the enclosing
try
statements for a matching
except
clause. The effect of a
raise
statement is to either divert execution in a
matching
except
suite, or to stop the program because
no matching
except
suite was found to handle the
exception.
The exception
object created by
raise
can contain a message string that provides a
meaningful error message. In addition to the string, it is relatively
simple to attach additional attributes to the exception.
Here are the two forms for the
raise
satement.
raise
exceptionClass
〈,
value
〉
The first form of the
raise
statement uses an
exception class name. The optional parameter is the additional value
that will be contained in the exception. Generally, this is a
string
.
Here's an example of the
raise
statement.
raise ValueError, "oh dear me"
This statement raises the built-in exception
ValueError
with an amplifying
string
of "oh dear me"
. The
amplifying string
in this example, one might
argue, is of no use to anybody. This is an important consideration in
exception design. When using a built-in exception, be sure that the
parameter string
pinpoints the error
condition.
The second form of the raise statement uses an object constructor
to create the Exception
object.
raise ValueError( "oh dear me" )
Here's a variation on the second form in which additional
attributes are provided for the exception.
ex= MyNewError( "oh dear me" )
ex.myCode= 42
ex.myType= "O+"
raise ex
In this case a handler can make use of the message, as well as the
two additional attributes, myCode
and
myType
.
Defining Your Own Exception. You will rarely have a need to raise a built-in exception. Most
often, you will need to define an exception which is unique to your
application.
We'll cover this in more detail as part of the object oriented
programming features of Python, in Chapter 21, Classes
.
Here's the short version of how to create your own unique exception
class.
class MyError( Exception ): pass
This single statement defines a subclass of
Exception
named MyError
.
You can then raise MyError
in a
raise
statement and check for
MyError
in
except
clauses.
Here's an example of defining a unique exception and raising this
exception with an amplifying string
.
Example 17.3. quadratic.py
import math
class QuadError( Exception ): pass
def quad(a,b,c):
if a == 0:
ex= QuadError( "Not Quadratic" )
ex.coef= ( a, b, c )
raise ex
if b*b-4*a*c < 0:
ex= QuadError( "No Real Roots" )
ex.coef= ( a, b, c )
raise ex
x1= (-b+math.sqrt(b*b-4*a*c))/(2*a)
x2= (-b-math.sqrt(b*b-4*a*c))/(2*a)
return (x1,x2)
An application that used this function might do something like
the following.
def quadReport( a, b, c ):
try:
x1, x2 = quad( a, b, c )
print "Roots are", x1, x2
except QuadError, ex:
print ex, ex.coef
Additional
raise
Statements. Exceptions can be raised anywhere, including in an
except
clause of a
try
statement. We'll look at two examples of re-raising an
exception.
We can use the simple
raise
statement in an
except
clause. This re-raises the original exception.
We can use this to do standardized error handling. For example, we might
write an error message to a log file, or we might have a standardized
exception clean-up process.
try:
attempt something risky
except Exception, ex:
log_the_error( ex )
raise
This shows how we might write the exception to a standard log in
the function log_the_error
and then re-raise the
original exception again. This allows the overall application to choose
whether to stop running gracefully or handle the exception.
The other common technique is to transform Python errors into our
application's unique errors. Here's an example that logs an error and
transforms the built-in
FloatingPointError
into our
application-specific error,
MyError
.
class MyError( Exception ): pass
try:
attempt something risky
except FloatingPointError, e:
do something locally, perhaps to clean up
raise MyError("something risky failed: %s" % ( e, ) )
This allows us to have more consistent error messages, or to hide
implementation details.