[Python-Dev] Bug in Pickle protocol involving __setstate__

Thomas Wouters thomas at python.org
Tue Mar 18 22:48:26 CET 2008


On Mon, Mar 3, 2008 at 8:00 AM, Greg Kochanski <greg.kochanski at phon.ox.ac.uk>
wrote:

> If we have a hierarchy of classes, and we use
> __getstate__/__setstate__, the wrong version
> of __setstate__ gets called.
>
> Possibly, this is a documentation problem, but here goes:
>

No, it's a typo error :)


>
> Take two classes, A and B, where B is the child of A.
>
> Construct a B.   Pickle it.   Unpickle it, and you find
> that the __setstate__ function for A is called with the result
> produced by B.__getstate__().
>
> This is wrong.
>
>
> An example follows:
>
> import pickle as P
>
>
> class A(object):
>         def __init__(self, a):
>                 print 'A.__init__'
>                 self.a = a
>
>         def __getstate__(self):
>                 print 'A.__getstate'
>                 return self.a
>
>         def __setstate__(self, upstate):
>                 print 'A.__setstate', upstate
>                 self.a = upstate
>
> class B(A):
>         def __init__(self, a, b):
>                 print 'B.__init__'
>                 A.__init__(self, a)
>                 self.b = b
>
>         def __getstate__(self):
>                 print 'B.__getstate'
>                 return (A.__getstate__(self), self.b)
>
>         def __setstate(self, upstate):


Try actually calling this method '__setstate__' instead.


>                # This never gets called!
>                 print 'B.__setstate', upstate
>                 A.__setstate__(self, upstate[0])
>                 self.b = upstate[1]
>
>
>         def __repr__(self):
>                 return '<B a=%d b=%d>' % (self.a, self.b)
>
>
> q = B(1,2)
> print '---'
> r = P.loads(P.dumps(q, 0))
> print 'q=', q
> print 'r=', r
>
>
> Now, run it:
>
> $ python foo.py
> B.__init__
> A.__init__
> ---
> B.__getstate
> A.__getstate
> A.__setstate (1, 2)
> q= <B a=1 b=2, h=46912504218064>
> r= Traceback (most recent call last):
>   File "foo.py", line 44, in <module>
>     print 'r=', r
>   File "foo.py", line 37, in __repr__
>     return '<B a=%d b=%d>' % (self.a, self.b)
> AttributeError: 'B' object has no attribute 'b'
> $
> _______________________________________________
> Python-Dev mailing list
> Python-Dev at python.org
> http://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> http://mail.python.org/mailman/options/python-dev/thomas%40python.org
>



-- 
Thomas Wouters <thomas at python.org>

Hi! I'm a .signature virus! copy me into your .signature file to help me
spread!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.python.org/pipermail/python-dev/attachments/20080318/9f200a4b/attachment.htm 


More information about the Python-Dev mailing list