26.2 Exception IdiomsWe've seen the mechanics behind exceptions. Now, let's take a look at some of the other ways they are typically used. 26.2.1 Exceptions Aren't Always Errors
In Python, all errors are exceptions, but not all exceptions are errors. For instance, we saw in Chapter 7 that file object read
Despite its
while 1:
try:
line = raw_input( ) # Read line from stdin.
except EOFError:
break # Exit loop at end of file
else:
...process next line here...
Other built-in exceptions are similarly signals, not errors. Python also has a set of built-in exceptions that represent warnings , rather than errors. Some of these are used to signal use of deprecated (phased out) language features. See the standard library manual's description of built-in exceptions and the warnings module for more on warnings. 26.2.2 Functions Signal Conditions with raiseUser-defined exceptions can also signal nonerror conditions. For instance, a search routine can be coded to raise an exception when a match is found, instead of returning a status flag that must be interpreted by the caller. In the following, the try / except / else exception handler does the work of an if / else return value tester:
Found = "Item found"
def searcher( ):
if ...
success
...:
raise Found
else:
return
try:
searcher( )
except Found: # Exception if item was found
...success...
else: # else returned: not found
...failure...
More
failure = "not found"
def searcher( ):
if ...
success
...:
return ...
founditem
...
else:
raise failure
try:
item = searcher( )
except failure:
...
report
...
else:
...use item here...
Because Python is dynamically typed and polymorphic to the
26.2.3 Debugging with Outer try StatementsYou can also make use of exception handlers to replace Python's default top-level exception-handling behavior. By wrapping an entire program (or a call to it) in an outer try in your top-level code, you can catch any exception that may occur while your program runs, thereby subverting the default program termination. In the following, the empty except clause catches any uncaught exception raised while the program runs. To get hold of the actual exception that occurred, fetch the exc_type and exc_value attributes from the built-in sys module; they're automatically set to the current exception's name and extra data: [1]
try:
...run program...
except: # All uncaught exceptions come here.
import sys
print 'uncaught!', sys.exc_type, sys.exc_value
This structure is commonly used during development, to keep your program active even after errors occur—you can run additional tests without having to restart. It's also used when testing code, as described in the next section. 26.2.4 Running in-Process TestsYou might combine some of these coding patterns in a test-driver application, which tests other code within the same process:
import sys
log = open('testlog', 'a')
from testapi import moreTests, runNextTest, testName
def testdriver( ):
while moreTests( ):
try:
runNextTest( )
except:
print >> log, 'FAILED', testName( ), sys.exc_type
else:
print >> log, 'PASSED', testName( )
testdriver( )
The testdriver function here cycles through a series of test calls (module testapi is left abstract in this example). Because an uncaught exception in a test case would normally kill this test driver, we need to wrap test case calls in a try if we want to continue the testing process after a test fails. As usual, the empty except catches any uncaught exception generated by a test case, and uses sys.exc_type to log the exception to a file; the else clause is run when no exception occurs—the test success case.
Such
|