How do I raise an exception in Python so that it can later be caught via an except
block?
Python Exception Handling – Manually Raising an Exception
exceptionpython
exceptionpython
How do I raise an exception in Python so that it can later be caught via an except
block?
Best Answer
Use the most specific Exception constructor that semantically fits your issue.
Be specific in your message, e.g.:
Don't raise generic exceptions
Avoid raising a generic
Exception
. To catch it, you'll have to catch all other more specific exceptions that subclass it.Problem 1: Hiding bugs
For example:
Problem 2: Won't catch
And more specific catches won't catch the general exception:
Best Practices:
raise
statementInstead, use the most specific Exception constructor that semantically fits your issue.
which also handily allows an arbitrary number of arguments to be passed to the constructor:
These arguments are accessed by the
args
attribute on theException
object. For example:prints
In Python 2.5, an actual
message
attribute was added toBaseException
in favor of encouraging users to subclass Exceptions and stop usingargs
, but the introduction ofmessage
and the original deprecation of args has been retracted.Best Practices:
except
clauseWhen inside an except clause, you might want to, for example, log that a specific type of error happened, and then re-raise. The best way to do this while preserving the stack trace is to use a bare raise statement. For example:
Don't modify your errors... but if you insist.
You can preserve the stacktrace (and error value) with
sys.exc_info()
, but this is way more error prone and has compatibility problems between Python 2 and 3, prefer to use a bareraise
to re-raise.To explain - the
sys.exc_info()
returns the type, value, and traceback.This is the syntax in Python 2 - note this is not compatible with Python 3:
If you want to, you can modify what happens with your new raise - e.g. setting new
args
for the instance:And we have preserved the whole traceback while modifying the args. Note that this is not a best practice and it is invalid syntax in Python 3 (making keeping compatibility much harder to work around).
In Python 3:
Again: avoid manually manipulating tracebacks. It's less efficient and more error prone. And if you're using threading and
sys.exc_info
you may even get the wrong traceback (especially if you're using exception handling for control flow - which I'd personally tend to avoid.)Python 3, Exception chaining
In Python 3, you can chain Exceptions, which preserve tracebacks:
Be aware:
Deprecated Methods:
These can easily hide and even get into production code. You want to raise an exception, and doing them will raise an exception, but not the one intended!
Valid in Python 2, but not in Python 3 is the following:
Only valid in much older versions of Python (2.4 and lower), you may still see people raising strings:
In all modern versions, this will actually raise a
TypeError
, because you're not raising aBaseException
type. If you're not checking for the right exception and don't have a reviewer that's aware of the issue, it could get into production.Example Usage
I raise Exceptions to warn consumers of my API if they're using it incorrectly:
Create your own error types when apropos
You can create your own error types, if you want to indicate something specific is wrong with your application, just subclass the appropriate point in the exception hierarchy:
and usage: