My background is in C# and I've just recently started programming in Python. When an exception is thrown I typically want to wrap it in another exception that adds more information, while still showing the full stack trace. It's quite easy in C#, but how do I do it in Python?
Eg. in C# I would do something like this:
try
{
ProcessFile(filePath);
}
catch (Exception ex)
{
throw new ApplicationException("Failed to process file " + filePath, ex);
}
In Python I can do something similar:
try:
ProcessFile(filePath)
except Exception as e:
raise Exception('Failed to process file ' + filePath, e)
...but this loses the traceback of the inner exception!
Edit: I'd like to see both exception messages and both stack traces and correlate the two. That is, I want to see in the output that exception X occurred here and then exception Y there - same as I would in C#. Is this possible in Python 2.6? Looks like the best I can do so far (based on Glenn Maynard's answer) is:
try:
ProcessFile(filePath)
except Exception as e:
raise Exception('Failed to process file' + filePath, e), None, sys.exc_info()[2]
This includes both the messages and both the tracebacks, but it doesn't show which exception occurred where in the traceback.
Assuming:
raise ... from
solution)you can use a simple solution from the the docs https://docs.python.org/3/tutorial/errors.html#raising-exceptions:
The output:
It looks like the key piece is the simplified 'raise' keyword that stands alone. That will re-raise the Exception in the except block.
Python 3 has the
raise
...from
clause to chain exceptions. Glenn's answer is great for Python 2.7, but it only uses the original exception's traceback and throws away the error message and other details. Here are some examples in Python 2.7 that add context information from the current scope into the original exception's error message, but keep other details intact.Known Exception Type
That flavour of
raise
statement takes the exception type as the first expression, the exception class constructor arguments in a tuple as the second expression, and the traceback as the third expression. If you're running earlier than Python 2.2, see the warnings onsys.exc_info()
.Any Exception Type
Here's another example that's more general purpose if you don't know what kind of exceptions your code might have to catch. The downside is that it loses the exception type and just raises a RuntimeError. You have to import the
traceback
module.Modify the Message
Here's another option if the exception type will let you add context to it. You can modify the exception's message and then reraise it.
That generates the following stack trace:
You can see that it shows the line where
check_output()
was called, but the exception message now includes the command line.It's simple; pass the traceback as the third argument to raise.
Always do this when catching one exception and re-raising another.