How to serialize an Exception

12,956

Solution 1

Exceptions can not be pickled (by default), you have two options:

  1. Use Python's built in format_exc() and serialize the formatted string.

  2. 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())

Solution 2

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)))
Share:
12,956
sds
Author by

sds

Math, Data Science, History...

Updated on July 19, 2022

Comments

  • sds
    sds almost 2 years

    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"
      }
    }