Learning Python - Mark Lutz [449]
File " IndexError: string index out of range Because our code does not explicitly catch this exception, it filters back up to the top level of the program and invokes the default exception handler, which simply prints the standard error message. By this point in the book, you’ve probably seen your share of standard error messages. They include the exception that was raised, along with a stack trace—a list of all the lines and functions that were active when the exception occurred. The error message text here was printed by Python 3.0; it can vary slightly per release, and even per interactive shell. When coding interactively in the basic shell interface, the filename is just “ >>> fetcher(x, 4) # Default handler - IDLE GUI interface Traceback (most recent call last): File " fetcher(x, 4) File " return obj[index] IndexError: string index out of range In a more realistic program launched outside the interactive prompt, after printing an error message the default handler at the top also terminates the program immediately. That course of action makes sense for simple scripts; errors often should be fatal, and the best you can do when they occur is inspect the standard error message. Catching Exceptions Sometimes, this isn’t what you want, though. Server programs, for instance, typically need to remain active even after internal errors. If you don’t want the default exception behavior, wrap the call in a try statement to catch exceptions yourself: >>> try: ... fetcher(x, 4) ... except IndexError: # Catch and recover ... print('got exception') ... got exception >>> Now, Python jumps to your handler (the block under the except clause that names the exception raised) automatically when an exception is triggered while the try block is running. When working interactively like this, after the except clause runs, we wind up back at the Python prompt. In a more realistic program, try statements not only catch exceptions, but also recover from them: >>> def catcher(): ... try: ... fetcher(x, 4) ... except IndexError: ... print('got exception') ... print('continuing') ... >>> catcher() got exception continuing >>> This time, after the exception is caught and handled, the program resumes execution after the entire try statement that caught it—which is why we get the “continuing” message here. We don’t see the standard error message, and the program continues on its way normally. Raising Exceptions So far, we’ve been letting Python raise exceptions for us by making mistakes (on purpose this time!), but our scripts can raise exceptions too—that is, exceptions can be raised by Python or by your program, and can be caught or not. To trigger an exception manually, simply run a raise statement. User-triggered exceptions are caught the same way as those Python raises. The following may not be the most useful Python code ever penned, but it makes the point: >>> try: ... raise IndexError # Trigger exception manually ... except IndexError: ... print('got exception') ... got exception As usual, if they’re not caught, user-triggered exceptions are propagated up to the top-level default exception handler and terminate the program with a standard error message: >>> raise IndexError Traceback (most recent call last): File " IndexError As we’ll see in the next chapter, the assert statement can be used to trigger exceptions, too—it’s a conditional raise, used mostly for debugging purposes during development: >>> assert False, 'Nobody expects the Spanish Inquisition!' Traceback (most recent call last): File "