When I try to serialize an exception using json.dump
, I get errors like
TypeError: IOError('socket error', error(61, 'Connection refused')) is not JSON serializable
and
TypeError: error(61, 'Connection refused') is not JSON serializable
The __dict__
field of exceptions is {}
(this is why How to make a class JSON serializable does not help me: the answers there assume that __dict__
contains all the necessary information, they also assume that I have control over the class to be serialized).
Is there something more intelligent that saving str(exn)
?
I would prefer a human-readable text representation (not pickle
).
PS. Here is what I came up with:
def exception_as_dict(ex):
return dict(type=ex.__class__.__name__,
errno=ex.errno, message=ex.message,
strerror=exception_as_dict(ex.strerror)
if isinstance(ex.strerror,Exception) else ex.strerror)
json.dumps(exception_as_dict(err),indent=2)
{
"errno": "socket error",
"type": "IOError",
"strerror": {
"errno": 61,
"type": "error",
"strerror": "Connection refused"
}
}
SerializationException(String, Exception) Initializes a new instance of the SerializationException class with a specified error message and a reference to the inner exception that is the cause of this exception.
If you're trying to serialize the exception for a log, it might be better to do a . ToString(), and then serialize that to your log. But here's an article about how to do it, and why. Basically, you need to implement ISerializable on your exception.
All exceptions by default are serializable and that's a language design decision because the authors wanted exceptions to be capable of being sent across the wire without any special configuration.
You can use exc_info
with traceback
as below:
import traceback
import sys
try:
raise KeyError('aaa!!!')
except Exception as e:
exc_info = sys.exc_info()
print(''.join(traceback.format_exception(*exc_info)))
Exceptions can not be pickled (by default), you have two options:
Use Python's built in format_exc() and serialize the formatted string.
Use tblib
With the latter, you can pass wrapped exceptions and also reraise them later.
import tblib.pickling_support
tblib.pickling_support.install()
import pickle, sys
def inner_0():
raise Exception('fail')
def inner_1():
inner_0()
def inner_2():
inner_1()
try:
inner_2()
except:
s1 = pickle.dumps(sys.exc_info())
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With