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.
In Python 3.x:
or simply
which will propagate
MyException
but print both exceptions if it will not be handled.In Python 2.x:
You can prevent printing both exceptions by killing the
__context__
attribute. Here I write a context manager using that to catch and change your exception on the fly: (see http://docs.python.org/3.1/library/stdtypes.html for expanation of how they work)For maximum compatibility between Python 2 and 3, you can use
raise_from
in thesix
library. https://six.readthedocs.io/#six.raise_from . Here is your example (slightly modified for clarity):You could use my CausedException class to chain exceptions in Python 2.x (and even in Python 3 it can be useful in case you want to give more than one caught exception as cause to a newly raised exception). Maybe it can help you.
Maybe you could grab the relevant information and pass it up? I'm thinking something like:
I don't think you can do this in Python 2.x, but something similar to this functionality is part of Python 3. From PEP 3134:
Comparison to C#:
Note also that Java, Ruby and Perl 5 don't support this type of thing either. Quoting again:
In python 3 you can do the following:
This will produce something like this: