6.1 The try Statement
The try statement
provides Python's exception-handling mechanism. It
is a compound statement that can take one of two different forms:
6.1.1 try/except
Here's the syntax for the
try/except form of the
try statement:
try:
statement(s)
except [expression [, target]]:
statement(s)
[else:
statement(s)]
This form of the try statement has one or more
except clauses, as well as an optional
else clause.
The body of each except clause is known as an
exception handler. The code
executes if the expression in the
except clause matches an exception object that
propagates from the try clause.
expression is an optional class or tuple
of classes that matches any exception object of one of the listed
classes or any of their subclasses. The optional
target is an identifier that names a
variable that Python binds to the exception object just before the
exception handler executes. A handler can also obtain the current
exception object by calling the exc_info function
of module sys (covered in Chapter 8).
Here is an example of the
try/except form of the
try statement:
try: 1/0
except ZeroDivisionError: print "caught divide-by-0 attempt"
If a try statement has several
except clauses, the exception propagation
mechanism tests the except clauses in order: the
first except clause whose expression matches the
exception object is used as the handler. Thus, you must always list
handlers for specific cases before you list handlers for more general
cases. If you list a general case first, the more specific
except clauses that follow will never enter the
picture.
The last except clause may lack an expression.
This clause handles any exception that reaches it during propagation.
Such unconditional handling is a rare need, but it does occur,
generally in wrapper functions that must perform some extra task
before reraising an exception, as we'll discuss
later in the chapter.
Note that exception propagation terminates when it finds a handler
whose expression matches the exception object. Thus, if a
try statement is nested in the
try clause of another try
statement, a handler established by the inner try
is reached first during propagation, and therefore is the one that
handles the exception, if it matches the expression. For example:
try:
try: 1/0
except: print "caught an exception"
except ZeroDivisionError:
print "caught divide-by-0 attempt"
# prints: caught an exception
In this case, it does not matter that the handler established by
clause except
ZeroDivisionError: in the outer
try clause is more specific and appropriate than
the catch-all except: in the inner
try clause. The outer try does
not even enter into the picture because the exception
doesn't propagate out of the inner
try.
The optional else clause of
try/except executes only if the
try clause terminates normally. In other words, it
does not execute if an exception propagates from the
try clause or if the try clause
exits with a break, continue,
or return statement. The handlers established by
try/except cover only the
try clause, not the else
clause. The else clause is useful to avoid
accidentally handling unexpected exceptions. For example:
print repr(value), "is ",
try:
value + 0
except TypeError:
# not a number, maybe a string, Unicode, UserString...?
try:
value + ''
except TypeError:
print "neither a number nor a string"
else:
print "a string or string-like value"
else:
print "a number of some kind"
6.1.2 try/finally
Here's the syntax for the
try/finally form of the
try statement:
try:
statement(s)
finally:
statement(s)
This form has exactly one finally clause, and it
cannot have an else clause.
The finally clause establishes what is known as a
clean-up handler. The code
always executes after the try clause terminates in
any way. When an exception propagates from the try
clause, the try clause terminates, the clean-up
handler executes, and the exception keeps propagating. When no
exception occurs, the clean-up handler executes anyway, whether the
try clause reaches its end or exits by executing a
break, continue, or
return statement.
Clean-up handlers established with try/finally
offer a robust and explicit way to specify finalization code that
must always execute, no matter what, to ensure consistency of program
state and/or external entities (e.g., files, databases, network
connections). Here is an example of the
try/finally form of the
try statement:
f = open(someFile, "w")
try:
do_something_with_file(f)
finally:
f.close( )
Note that the try/finally form
is distinct from the try/except
form: a try statement cannot have both
except and finally clauses, as
execution order might be ambiguous. If you need both exception
handlers and a clean-up handler, nest a try
statement in the try clause of another
try statement to define execution order explicitly
and unambiguously.
A finally clause cannot directly contain a
continue statement, but it may contain a
break or return statement. Such
usage, however, makes your program less clear, as exception
propagation stops when such a break or
return executes. Most programmers would not
normally expect propagation to be stopped in a
finally clause, so this usage may confuse people
who are reading your code.
|