To trigger exceptions explicitly, you code raise statements. Their general form is simple the word raise, optionally followed by both the name of the exception to be raised and an extra data item to pass with the exception: raise <name> # Manually trigger an exception. raise <name>, <data> # Pass extra data to catcher too. raise # Reraise the most recent exception. The second form allows you to pass an extra data item along with the exception, to provide details for the handler. In the raise, the data is listed after the exception name; back in the try statement, the data is obtained by including a variable to receive it. For instance, in except name,X:, X will be assigned the extra data item listed at the raise. The third raise form simply reraises the current exception; it's handy if you want to propagate an exception you've caught to another handler. So what's an exception name? It might be the name of a built-in exception from the built-in scope (e.g., IndexError), or the name of an arbitrary string object you've assigned in your program. It can also reference a user-defined class or class instance a possibility that further generalizes raise statement formats. We'll postpone the details of this generalization until after we have a chance to study class exceptions in the next chapter. Regardless of how you name exceptions, they are always identified by normal objects, and at most one is active at any given time. Once caught by an except clause anywhere in the program, an exception dies (won't propagate to another try), unless reraised by another raise statement or error. 24.5.1 Example: Raising and Catching User-Defined ExceptionsPython programs can trigger both built-in and user-defined exceptions, using the raise statement. In their simplest form, user-defined exceptions are string objects, like the one that variable MyBad is assigned to in the following: MyBad = "oops" def stuff( ): raise MyBad # Trigger exception manually. try: stuff( ) # Raises exception except MyBad: print 'got it' # Handle exception here. ... # Resume execution here. This time, the raise occurs inside a function, but it makes no real difference control jumps back to the except block immediately. Notice that user-defined exceptions are caught with try statements just like built-in exceptions. 24.5.2 Example: Passing Extra Data with raiseAs suggested earlier, raise statements can pass an extra data item along with the exception for use in a handler. In general, the extra data allows you to send context information about the exception to a handler. If you're writing a data file parser, for example, you might raise a syntax error exception on errors, and also pass along an object that gives line and file information to the handler (we'll meet an example of such later in this part). Strictly speaking, every exception has the extra data: much like function return values, it defaults to the special None object if nothing was passed explicitly. The following code, raisedata.py, illustrates this concept at work: myException = 'Error' # String object def raiser1( ): raise myException, "hello" # Raise, pass data. def raiser2( ): raise myException # Raise, None implied. def tryer(func): try: func( ) except myException, extraInfo: # Run func; catch exception+data. print 'got this:', extraInfo % python >>> from raisedata import * >>> tryer(raiser1) # Explicitly passed extra data got this: hello >>> tryer(raiser2) # Extra data is None by default. got this: None Here, the tryer function always requests the extra data object; it comes back as an explicit string from raiser1, but defaults to None in raiser2's raise statement. Later, we'll see that the same hook can be used to access instances raised in conjunction with class-based exceptions. 24.5.3 Example: Propagating Exceptions with raiseA raise statement without an exception name or extra data value simply reraises the current exception. It's typically used if you need to catch and handle an exception, but don't want the exception to die in your code: >>> try: ... raise IndexError, 'spam' ... except IndexError: ... print 'propagating' ... raise ... propagating Traceback (most recent call last): File "<stdin>", line 2, in ? IndexError: spam By running a raise this way, the exception will be reraised and thus propagated to a higher handler, or to the default handler at the top, which stops the program with a standard error message. |