How can I raise an exception in Python so that it can later be caught via an except
block?
相关问题
- how to define constructor for Python's new Nam
- streaming md5sum of contents of a large remote tar
- How to get the background from multiple images by
- Evil ctypes hack in python
- Correctly parse PDF paragraphs with Python
Read the existing answers first, this is just an addendum.
Notice that you can raise exceptions with or without arguments.
Example:
exits the program but you might want to know what happened.So you can use this.
this will print "program exited" to stderr before closing the program.
In Python3 there are 4 different syntaxes for rasing exceptions:
If you use
raise exception (args)
to raise an exception then theargs
will be printed when you print the exception object - as shown in the example below.raise
statement without any arguments re-raises the last exception. This is useful if you need to perform some actions after catching the exception and then want to re-raise it. But if there was no exception before,raise
statement raisesTypeError
Exception.This statement is used to create exception chaining in which an exception that is raised in response to another exception can contain the details of the original exception - as shown in the example below.
Output:
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 the Exception object. For example:prints
In Python 2.5, an actual
message
attribute was added to BaseException 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 a BaseException 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:
Can't get much more pythonic than this:
See the raise statement docs for python if you'd like more info.
For the common case where you need to throw an exception in response to some unexpected conditions, and that you never intend to catch, but simply to fail fast to enable you to debug from there if it ever happens — the most logical one seems to be
AssertionError
:Just to note: there are times when you DO want to handle generic exceptions. If you're processing a bunch of files and logging your errors, you might want to catch any error that occurs for a file, log it, and continue processing the rest of the files. In that case, try: except Exception: is a good way to do it. You'll still want to raise specific exceptions so you know what they mean though.