[Python-Dev] Bug in Pickle protocol involving __setstate__

Greg Kochanski greg.kochanski at phon.ox.ac.uk
Mon Mar 3 18:56:08 CET 2008

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:

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):
		# 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
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'

More information about the Python-Dev mailing list