Exceptions
Exceptions are used to report errors or other exceptional conditions. If an exceptions is not handled, it will print a traceback indicating what kind of exception occurred and where it originated in the code.
Exceptions are reported with the raise
statement.
An error message can be supplied in parentheses.
There are many kinds
of exceptions.
They all derive from BaseException
and most derive from Exception
.
Some of the more common ones are:
TypeError
: raised by functions to indicate that an argument is of incorrect type, such as passing astr
where anint
orfloat
was expected.ValueError
: raised by functions to indicate that an argument is of the correct type but contains an invalid value, such as passing a negative number to a function that requires a nonnegative value.KeyError
: raised when adict
key does not exist.IndexError
: raised when an index to a sequence is out of range.
It is common to write functions to check the type and value of arguments and
raise TypeError
or ValueError
before attempting to manipulate them.
Here is an example factorial
function which verifies the type and value of its
parameter:
Note that Python favors
duck typing, which means
identifying an object’s “type” by its abilities, not its actual type (class).
Using duck typing, the above factorial
function would not explicitly use the
isinstance
function, but assume that n
“acts” like an int
, i.e. it defines
the comparison and arithmetic operators as used by factorial
.
When implementing your own library, it is common to define your own exceptions
which are specific to your library.
Exceptions are classes which inherit from Exception
.
Since the only important part of an exception’s definition is its type, and all
of the required logic is implemented in Exception
, the custom exception’s body
can consist of only a docstring or the
pass
statement.
The try
Statement
The try
statement is used to handle exceptions.
Any code which might produce an exception that you want to handle must go in a
try
block.
The try
block must be followed by either an except
block or a finally
block.
The except
block is given the type of exception that you want it to handle.
You can bind the exception object to a name using the as
keyword.
There can be multiple except
blocks to check for different types of exceptions.
If an exception is raised by code in the try
block, the exception object’s
type is checked against the types of the following except
blocks; the first
matching block is executed.
This means that you must put except
blocks for more specific types of
exceptions before any except
blocks for more general types of exceptions;
if you put the more general type first then the more specific block won’t be
executed.
The last except
block can omit the exception type; this is used to catch all
exceptions.
Within an except
block, the raise
statement without an argument will
re-raise the exception; this is used to add cleanup code while still propagating
the exception.
After all except
blocks, there can be an else
block, which is executed only
if the try
block completed without exceptions.
A finally
block is can be placed at the end of the try
statement.
The finally
block is always executed, regardless of whether an exception
occurred or not.
See the try statement.
The with
Statement
The with
statement is used to wrap a block with methods defined by a
context manager.
A context manager is defined by the methods __enter__
and __exit__
.
The expression given to with
must evaluate to a context manager.
The context manager’s __enter__
method is called and the return value is bound
to the name following as
.
When the with
block terminates, the context manager’s __exit__
method is
called.
The __exit__
method is always called, whether the with
block terminated
normally or due to an unhandled exception.
Python’s built-in file
type is a context manager whose __enter__
returns
itself and __exit__
closes the file.
Using files in a with
statement ensures that they are closed properly.
Without the with
statement, the above would have to be written like this:
See PEP 343.