Hi all,<br><br>I'm migrating code from python 2.4 to python 2.6 and I've got into troubles with pickling/unpickling  python Exceptions.<br>The following code works fine in 2.4 but not in 2.6.<br>See Exception1 example<br>

<br>I have found on python mail list similar problem <br><a href="http://mail.python.org/pipermail/python-list/2009-December/1228773.html" target="_blank">http://mail.python.org/pipermail/python-list/2009-December/1228773.html</a><br>

They recommend to use __reduce__. But this does not help as I'm getting different Exception class after pickle<br>See Exception_with_reduce example<br><br>I also have found possible solution to this problem here<br><a href="http://bugs.python.org/issue1692335">http://bugs.python.org/issue1692335</a><br>

As a workaround they propose to pass Exception arguments into base class<br>See Exception2 example<br>But there is another problem. Constructor is called 2 times which is not acceptable to me.<br><br>Could you please advice on the solution?<br>

<br>------------------------------------------<br>test program<br>------------------------------------------<br>import cPickle<br><br>class Exception1(Exception):<br>    def __init__(self,arg1):<br>        print "constructor called"<br>

        Exception.__init__(self)<br>        <br>class Exception2(Exception):<br>    def __init__(self,arg1):<br>        print "constructor called"<br>        Exception.__init__(self,arg1)<br><br>class Exception_with_reduce(Exception):<br>

    def __reduce__(self):<br>        try:<br>            getnewargs = self.__getnewargs__<br>        except AttributeError:<br>            newargs = (self.__class__,)<br>        else:<br>            newargs = (self.__class__,) + getnewargs()<br>

        <br>        try:<br>            getstate = self.__getstate__<br>        except AttributeError:<br>            state = self.__dict__<br>        else:<br>            state = getstate()<br>        return (Exception, newargs, state)<br>

    <br>    def __init__(self,arg1):<br>        print "constructor called"<br>        Exception.__init__(self,arg1)<br><br>def test(E,args):<br>    try:<br>        print ">>",E.__name__<br>        e = E(*args)<br>

        print "- pickling"<br>        s = cPickle.dumps(e)<br>        print "- unpickling"<br>        e = cPickle.loads(s)<br>        <br>        if E != e.__class__:<br>            print "! failed: expected %s, got %s"%(E.__name__,e.__class__.__name__)<br>

    except Exception, e:<br>        print "! failed:",e<br>        <br>    print "\ finished"<br>    print <br>    <br>    <br>import os<br>if os.path.isfile("/home/ast1/blabla"):<br>    try:<br>

        s = open("/home/ast1/blabla","r").read()<br>        e = cPickle.loads(s)<br>        print e.__class__<br>    except Exception, e:<br>        print "error:",e<br>    <br>test(Exception1,[1])<br>

test(Exception2,[1])<br>test(Exception_with_reduce,[1])<br>------------------------------------------<br><br><br>------------------------------------------<br>
run results on python 2.6:<br>
------------------------------------------<br>
<br>
constructor called<br><class '__main__.Exception2'><br>>> Exception1<br>constructor called<br>- pickling<br>- unpickling<br>! failed: ('__init__() takes exactly 2 arguments (1 given)', <class '__main__.Exception1'>, ())<br>

\ finished<br><br>>> Exception2<br>constructor called<br>- pickling<br>- unpickling<br>constructor called<br>\ finished<br><br>>> Exception_with_reduce<br>constructor called<br>- pickling<br>- unpickling<br>! failed: expected Exception_with_reduce, got Exception<br>

\ finished<br><br>------------------------------------------<br>

run results on python 2.4:<br>

------------------------------------------<br>

<br>__main__.Exception2<br>>> Exception1<br>constructor called<br>- pickling<br>- unpickling<br>\ finished<br><br>>> Exception2<br>constructor called<br>- pickling<br>- unpickling<br>\ finished<br><br>>> Exception_with_reduce<br>

constructor called<br>- pickling<br>- unpickling<br>\ finished<br><br><br><br><br>