In the previous article, we covered some of the basics of exception handling in Python. In this article, we will go into a bit more detail on exception processing, and explore the details behind the try, raise, assert, and with statements.
Python Exceptions: Try, Raise, and Assert
We will start with the try statement, introduced in the previous article. The try statement is a compound statement which starts with a try header line, followed by a block of usually indented statements, then one or more except clauses that identify exceptions to be caught, and an optional else clause at the end. The words try, except and else are associated by indenting them to the same level. For example:
try
statements
except name1:
statements
except name2 as something:
statements
except:
statements
else:
statements
Here, the block under the try header represents the main action of the statement. This is the code you are trying to run. The except clauses define handlers for exceptions raised during the try block. The else clause, if coded, provides a handler to be run if no exceptions occur.
When a try statement is entered, Python marks the current program context so it can return to it if an exception occurs. The statements nested under the try header are run first. What happens next is dependent on whether exceptions are raised while the try block’s statements are running. If an exception does occur while the try block’s statements are running, Python jumps back to the try and runs the statements under the first except clause that matches the raised exception. Control resumes below the entire try statement after the except block runs, unless the except block raises another exception. But if an exception happens in the try block and no except clause matches, the exception is propagated up to the last matching try statement that was entered in the program, or (if it’s the first such statement) to the top level of the process. If it is at the top level of the process, Python will stop the program and print a default error message. Finally, if no exception occurs while the statements under the try header run, Python runs the statements under the else line, if there are any, and control then resumes below the entire try statement.
except clauses catch exceptions that occur only within the statements in the associated try block. As such, they are considered focused exception handlers. However, since the try block’s statements can call functions coded elsewhere in a program, the source of an exception may be outside the try statement itself.
There are several clauses you can use after the try header, but you have to use at least one. In addition, you can code else only if there is at least one else. There can be several except clauses, but there can only be one else and one finally. Through Python 2.4, the finally clasue must appear alone, without an else or except. As of Python 2.5, however, a finally can appear in the same statement as except and else.
Because Python looks for a match within a given try by inspecting the except caluses from top to bottom, the parenthesized version has the same effect as listing each exception in its own except clause, but with the benefit of only having to code the statement body once.
The empty except clause is a sort of wildcard feature; it catches everything. Therefore, it allows your handlers to be as general or specific as you like. This may be more convenient than listing all possible exceptions in a try. But empty except clasues raise some design issues. Although they are convenient, they may catch unexpected system calls unrelated to your code. For example, even system exit calls in Python trigger exceptions, and you usually want them to pass. For that reason, Python 3.0 introduced an alternative. Catching an exception named Exception has almost the same effect as an empty except, but ignores exceptions related to system exits. Other system calls, however, may still trigger exceptions.
Speak Your Mind