Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #28404 > unrolled thread

Why derivated exception can not be pickled ?

Started byMathieu Courtois <mathieu.courtois@gmail.com>
First post2012-09-04 08:57 -0700
Last post2012-09-05 03:18 -0700
Articles 6 — 3 participants

Back to article view | Back to comp.lang.python


Contents

  Why derivated exception can not be pickled ? Mathieu Courtois <mathieu.courtois@gmail.com> - 2012-09-04 08:57 -0700
    Re: Why derivated exception can not be pickled ? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-09-05 00:34 +0000
    Re: Why derivated exception can not be pickled ? Dieter Maurer <dieter@handshake.de> - 2012-09-05 08:02 +0200
      Re: Why derivated exception can not be pickled ? Mathieu Courtois <mathieu.courtois@gmail.com> - 2012-09-05 01:54 -0700
      Re: Why derivated exception can not be pickled ? Mathieu Courtois <mathieu.courtois@gmail.com> - 2012-09-05 01:54 -0700
    Re: Why derivated exception can not be pickled ? Mathieu Courtois <mathieu.courtois@gmail.com> - 2012-09-05 03:18 -0700

#28404 — Why derivated exception can not be pickled ?

FromMathieu Courtois <mathieu.courtois@gmail.com>
Date2012-09-04 08:57 -0700
SubjectWhy derivated exception can not be pickled ?
Message-ID<7bb72fb5-5ab5-4748-acbf-c8e7666ee834@googlegroups.com>
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.

[toc] | [next] | [standalone]


#28438

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2012-09-05 00:34 +0000
Message-ID<50469e1f$0$29981$c3e8da3$5496439d@news.astraweb.com>
In reply to#28404
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

[toc] | [prev] | [next] | [standalone]


#28454

FromDieter Maurer <dieter@handshake.de>
Date2012-09-05 08:02 +0200
Message-ID<mailman.211.1346824947.27098.python-list@python.org>
In reply to#28404
Mathieu Courtois <mathieu.courtois@gmail.com> 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.

[toc] | [prev] | [next] | [standalone]


#28468

FromMathieu Courtois <mathieu.courtois@gmail.com>
Date2012-09-05 01:54 -0700
Message-ID<f8fdaa79-5a58-4738-b18a-1df3f47abcba@googlegroups.com>
In reply to#28454
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

[toc] | [prev] | [next] | [standalone]


#28469

FromMathieu Courtois <mathieu.courtois@gmail.com>
Date2012-09-05 01:54 -0700
Message-ID<mailman.224.1346835264.27098.python-list@python.org>
In reply to#28454
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

[toc] | [prev] | [next] | [standalone]


#28476

FromMathieu Courtois <mathieu.courtois@gmail.com>
Date2012-09-05 03:18 -0700
Message-ID<daed0eb8-6100-4d05-b5b1-4d8ea56ac731@googlegroups.com>
In reply to#28404
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, ))

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web