As Steven suggests, you can do:
raise Exception('Invalid json: {}'.format(e)) from e
to get both exceptions printed, like this:
Traceback (most recent call last):File "tmp.py", line 5, in <module>raise Exception('Invalid json: {}'.format(e)) from eExceptionThe above exception was the direct cause of the following exception:Traceback (most recent call last):<...>json.decoder.JSONDecodeError: Expecting ',' delimiter: line 103 column 9 (char 1093)
Or you can do this:
raise Exception('Invalid json: {}'.format(e)) from None
To suppress the first one and only log the Invalid json...
exception.
By the way, doing something like raise Exception('Invalid json: {}'.format(e))
doesn't really make much sense, at that point you can just leave the original exception alone, since you're not adding much information to it.
Python is alerting you that you threw an exception while another one was in the process of being handled. The warning is there to alert you in case this was unexpected so that you know about the original exception. Consider a case like the following:
class Resource:def close(self):if cannot_close:raise Error("Cannot close")def write_data(self, data):...some_function():try:res = Resource()res.write_data("some data")except Error as e:res.close()
Let's say that write_data
raises an exception, but then the close
does so also, unexpectedly. When that happens, it's nice to know about both exceptions. In most cases, you want to know about the original exception raised by write_data
but knowing about the one from close
helps you know that something strange happened with close
.
But for your case, you are simply restating the original error in a new way. Doing so lets you provide more context, for example:
with open(json_file) as j:try:json_config = json.load(j)except ValueError as e:raise Exception('Invalid json from file {}: {}'.format(json_file, e))
This would provide you with the path of the file that failed to be parsed as JSON, which is helpful context information that won't be in the original exception message.
So to tell Python that you are essentially re-raising the original exception, but with more context, you add from e
.
with open(json_file) as j:try:json_config = json.load(j)except ValueError as e:raise Exception('Invalid json from file {}: {}'.format(json_file, e)) from e
This is equivalent to "exception chaining" in Java where you supply the original exception to the constructor of the new exception.
I have solved by using data.get(key)
instead of data[key]
.