Learning Python - Mark Lutz [471]
C:\misc> C:\Python30\python parse.py
C:\misc> type formaterror.txt
Error at spam.txt 40
In such a class, methods (like logerror) may also be inherited from superclasses, and instance attributes (like line and file) provide a place to save state information that provides extra context for use in later method calls. Moreover, exception classes are free to customize and extend inherited behavior. In other words, because they are defined with classes, all the benefits of OOP that we studied in Part VI are available for use with exceptions in Python.
* * *
[78] As suggested earlier, the raised instance object is also available generically as the second item in the result tuple of the sys.exc_info() call—a tool that returns information about the most recently raised exception. This interface must be used if you do not list an exception name in an except clause but still need access to the exception that occurred, or to any of its attached state information or methods. More on sys.exc_info in the next chapter.
Chapter Summary
In this chapter, we explored coding user-defined exceptions. As we learned, exceptions are implemented as class instance objects in Python 2.6 and 3.0 (an earlier string-based exception model alternative was available in earlier releases but has now been deprecated). Exception classes support the concept of exception hierarchies that ease maintenance, allow data and behavior to be attached to exceptions as instance attributes and methods, and allow exceptions to inherit data and behavior from superclasses.
We saw that in a try statement, catching a superclass catches that class as well as all subclasses below it in the class tree—superclasses become exception category names, and subclasses become more specific exception types within those categories. We also saw that the built-in exception superclasses we must inherit from provide usable defaults for printing and state retention, which we can override if desired.
The next chapter wraps up this part of the book by exploring some common use cases for exceptions and surveying tools commonly used by Python programmers. Before we get there, though, here’s this chapter’s quiz.
Test Your Knowledge: Quiz
What are the two new constraints on user-defined exceptions in Python 3.0?
How are raised class-based exceptions matched to handlers?
Name two ways that you can attach context information to exception objects.
Name two ways that you can specify the error message text for exception objects.
Why should you not use string-based exceptions anymore today?
Test Your Knowledge: Answers
In 3.0, exceptions must be defined by classes (that is, a class instance object is raised and caught). In addition, exception classes must be derived from the built-in class BaseException (most programs inherit from its Exception subclass, to support catchall handlers for normal kinds of exceptions).
Class-based exceptions match by superclass relationships: naming a superclass in an exception handler will catch instances of that class, as well as instances of any of its subclasses lower in the class tree. Because of this, you can think of superclasses as general exception categories and subclasses as more specific types of exceptions within those categories.
You can attach context information to class-based exceptions by filling out instance attributes in the instance object raised, usually in a custom class constructor. For simpler needs, built-in exception superclasses provide a constructor that stores its arguments on the instance automatically (in the attribute args). In exception handlers, you list a variable to be assigned to the raised instance, then go through this name to access attached state information and call any methods defined in the class.
The error message text in class-based exceptions can be specified with a custom __str__ operator overloading method. For simpler needs, built-in exception superclasses automatically display anything you pass to the class constructor.