Skip to content Skip to sidebar Skip to footer

Catching Unpickleable Exceptions And Re-raising

This is a followup to my question Hang in Python script using SQLAlchemy and multiprocessing. As discussed in that question, pickling exceptions is problematic in Python. This is u

Solution 1:

You can override sys.excepthook to achieve what you want. It at least works for this example, but it's pretty hacky so please test and no promises :-)

import sys

def excepthook_wrapper(type, value, traceback):
    iflen(value.args) == 2:
        name, msg = value.args
        value.args = (msg,)
        sys.__excepthook__(name, value, traceback)
    else:
        sys.__excepthook__(type, value, traceback)

sys.excepthook = excepthook_wrapper

(Edit: I'm not really happy with this because now 'normal' Exceptions with two arguments will get handled differently too. Possible solution, 'tag' your special Exceptions by passing "PICKLED" as a first argument and then check for that, instead of checking for the length of the args.)

And then create the Exception with two arguments, the name (__module__.__class__) and the Exception message (str(e)):

try:
    try:
        #print fooraise BadExc("bad exception error message", "a")
    except Exception, e:
        cls = e.__class__
        ifhasattr(cls, '__module__'):
            name = '{0}.{1}'.format(cls.__module__, cls.__name__)
        else:
            name = cls.__name__
        raise Exception(name, str(e)), None, sys.exc_info()[2]
except Exception, f:
    pass

Then this:

import cPickle
a = cPickle.dumps(f)
l = cPickle.loads(a)
print"raising error"raise sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]

Prints:

raising error
Traceback (most recent call last):
  File "test.py", line 18, in <module>
    raise BadExc("bad exception error message", "a")
__main__.BadExc: bad exception error message

Post a Comment for "Catching Unpickleable Exceptions And Re-raising"