Why derivated exception can not be pickled ?

Discussion in 'Python' started by Mathieu Courtois, Sep 4, 2012.

  1. Here is my example :


    import cPickle

    ParentClass = object # works
    ParentClass = Exception # does not

    class MyError(ParentClass):
    def __init__(self, arg):
    self.arg = arg

    def __getstate__(self):
    print '#DBG pass in getstate'
    odict = self.__dict__.copy()
    return odict

    def __setstate__(self, state):
    print '#DBG pass in setstate'
    self.__dict__.update(state)

    exc = MyError('IDMESS')

    fo = open('pick.1', 'w')
    cPickle.dump(exc, fo)
    fo.close()

    fo = open('pick.1', 'r')
    obj = cPickle.load(fo)
    fo.close()


    1. With ParentClass=object, it works as expected.

    2. With ParentClass=Exception, __getstate__/__setstate__ are not called.

    Does anyone explain me why ?
    Thanks.
     
    Mathieu Courtois, Sep 4, 2012
    #1
    1. Advertising

  2. On Tue, 04 Sep 2012 08:57:00 -0700, Mathieu Courtois wrote:

    > Here is my example :
    >
    >
    > import cPickle
    >
    > ParentClass = object # works
    > ParentClass = Exception # does not

    [...]
    > 1. With ParentClass=object, it works as expected.
    >
    > 2. With ParentClass=Exception, __getstate__/__setstate__ are not called.
    >
    > Does anyone explain me why ?



    I think it is a bug. According to the documentation, if your class is
    unpickleable, an exception should be raised. If it is pickleable,
    __getstate__ should be called. I can't see anything to explain that what
    you are seeing is expected behaviour.


    Exceptions should definitely be pickleable:

    http://bugs.python.org/issue1692335

    so __getstate__ should be called. I think you should report this as a bug.


    --
    Steven
     
    Steven D'Aprano, Sep 5, 2012
    #2
    1. Advertising

  3. Mathieu Courtois <> writes:

    > Here is my example :
    >
    >
    > import cPickle
    >
    > ParentClass = object # works
    > ParentClass = Exception # does not
    >
    > class MyError(ParentClass):
    > def __init__(self, arg):
    > self.arg = arg
    >
    > def __getstate__(self):
    > print '#DBG pass in getstate'
    > odict = self.__dict__.copy()
    > return odict
    >
    > def __setstate__(self, state):
    > print '#DBG pass in setstate'
    > self.__dict__.update(state)
    >
    > exc = MyError('IDMESS')
    >
    > fo = open('pick.1', 'w')
    > cPickle.dump(exc, fo)
    > fo.close()
    >
    > fo = open('pick.1', 'r')
    > obj = cPickle.load(fo)
    > fo.close()
    >
    >
    > 1. With ParentClass=object, it works as expected.
    >
    > 2. With ParentClass=Exception, __getstate__/__setstate__ are not called.


    The pickle interface is actually more complex and there are several
    ways an object can ensure picklability. For example, there is
    also a "__reduce__" method. I suppose, that "Exception" defines methods
    which trigger the use of an alternative picklability approach (different
    from "__getstate__/__setstate__").

    I would approach your case the following way: Use "pickle" instead
    of "cPickle" and debug picking/unpickling to find out what
    happens in detail.
     
    Dieter Maurer, Sep 5, 2012
    #3
  4. Thanks for your reply


    On Wednesday, September 5, 2012 8:02:55 AM UTC+2, Dieter Maurer wrote:
    >
    > The pickle interface is actually more complex and there are several
    >
    > ways an object can ensure picklability. For example, there is
    >
    > also a "__reduce__" method. I suppose, that "Exception" defines methods
    >
    > which trigger the use of an alternative picklability approach (different
    >
    > from "__getstate__/__setstate__").


    You're right: Exception has __reduce__ & __reduce_ex__ methods. Always read carefully the manual ;-)

    I must override these methods.


    MC
     
    Mathieu Courtois, Sep 5, 2012
    #4
  5. Thanks for your reply


    On Wednesday, September 5, 2012 8:02:55 AM UTC+2, Dieter Maurer wrote:
    >
    > The pickle interface is actually more complex and there are several
    >
    > ways an object can ensure picklability. For example, there is
    >
    > also a "__reduce__" method. I suppose, that "Exception" defines methods
    >
    > which trigger the use of an alternative picklability approach (different
    >
    > from "__getstate__/__setstate__").


    You're right: Exception has __reduce__ & __reduce_ex__ methods. Always read carefully the manual ;-)

    I must override these methods.


    MC
     
    Mathieu Courtois, Sep 5, 2012
    #5
  6. Hello,

    The simple example works fine using __reduce__:

    class MyError(Exception):
    def __init__(self, arg):
    self.arg = arg

    def __reduce__(self):
    return (MyError, (self.arg, ))
     
    Mathieu Courtois, Sep 5, 2012
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alexander Tumarov

    Default copy operator on derivated classes

    Alexander Tumarov, May 1, 2004, in forum: C++
    Replies:
    1
    Views:
    371
    Rob Williscroft
    May 1, 2004
  2. Replies:
    4
    Views:
    492
    Howard
    May 26, 2005
  3. Mr. SweatyFinger
    Replies:
    2
    Views:
    2,089
    Smokey Grindel
    Dec 2, 2006
  4. Lars Uffmann
    Replies:
    13
    Views:
    1,025
    Lars Uffmann
    Feb 19, 2008
  5. Stefan Schwarzer
    Replies:
    1
    Views:
    72
    Terry Reedy
    Apr 21, 2014
Loading...

Share This Page