Kurt Peek Kurt Peek - 1 month ago 7
Python Question

Use of "except Exception" vs. "except ... raise" in Python

I'm reading some source code which contains a function similar to the following:

def dummy_function():
try:
g = 1/0
except Exception as e:
raise Exception("There is an error: {}".format(e))


As I understand it, all exceptions are derived from the Exception class, so this should catch all errors. Following https://docs.python.org/3/tutorial/errors.html, then, would this not be equivalent to

def dummy_function():
try:
g = 1/0
except:
print "There is an error:"
raise


I notice that the printed output is arranged slightly differently in either case, but it would seem to me that the second method is basically the same and less verbose. Or am I missing something?

Answer

No, your code is not equivalent, for several reasons:

  • A blank except: catches all exceptions, including those derived from BaseException (SystemExit, KeyboardInterrupt and GeneratorExit); catching Exception filters out those exceptions you generally want to avoid catching without a re-raise. In older Python releases, it would also catch string exceptions (no longer permitted).
  • The except Exception as e catches subclasses, but then raises a new Exception() instance; the specific type information can't be used anymore in downstream try...except statements.
  • In Python 3, raising a new exception from an exception handler creates an exception chain (where the original exception is added as the Exception.__context__ attribute, see Python "raise from" usage)
  • The message is updated; that's probably the whole point here, is to give the exception a different message.

The code you found is.. rather bad practice. The top-level exception handler should just catch and print a message and perhaps a traceback, rather than re-raise the exception with a new message (and in Python 2 lose all information on the original exception, in Python 3 make it inaccessible to exception matching in later handlers).