Mailing List Archive

getstate, setstate and pickle
I've written a class, instantiated, then pickled the instance. At
first, pickling wouldn't work at all, but through some mix of
eliminating a class variable 'id' and adding __setstate__ and
__getstate__ methods it does dump (too soon to call it a pickle).

What I'm having trouble with is getting the load to match the dump. I
lifted parts of the pickle module test code, and the dump == load part
fails, then my code falls apart, and then nothing works... (I'm in
California, so picking grapes is an option ;-)

I'm probably not using get/set state properly. My instance should be
pickleable or I'd get an error there.

Any help or pointers to examples/docs appreciated.

--

Emile van Sebille
emile@fenx.com

NB: Perhaps builtins could be honorably mentioned along with reserved
words in the documentation. I'm now typing type(target) to get the
error as a result of my id problem above. In time, I'll know them. But
for now, it wasn't a pleasant bug to chase.
-------------------
getstate, setstate and pickle [ In reply to ]
Emile van Sebille wrote:
>
> I've written a class, instantiated, then pickled the instance. At
> first, pickling wouldn't work at all, but through some mix of
> eliminating a class variable 'id' and adding __setstate__ and
> __getstate__ methods it does dump (too soon to call it a pickle).
>
> What I'm having trouble with is getting the load to match the dump. I
> lifted parts of the pickle module test code, and the dump == load part
> fails, then my code falls apart, and then nothing works... (I'm in
> California, so picking grapes is an option ;-)
>
> I'm probably not using get/set state properly. My instance should be
> pickleable or I'd get an error there.
>
> Any help or pointers to examples/docs appreciated.

You don't need the __setstate__/__getstate__ methods unless you want to
exclude some instance variables from being pickled. On a normal class
the pickling should work without any problem. I also never had problems
with the name of the instance variables.

If you want to compare your own defined classes, don't forget to define
the __cmp__ method. This method defines how to compare instances of the
same class.

Here is a short example on how to pickle some objects:

from cPickle import Pickler, Unpickler
from StringIO import StringIO

class MyClass:
def __init__ (self, value):
self.value = value

def __repr__ (self):
return '[MyClass: %s]' % (self.value,)

def __cmp__ (self, other):
return self.value == other.value

object = MyClass (MyClass (123))
strIO = StringIO ()
pickler = Pickler (strIO)
pickler.dump (object)
strIO.seek (0, 0)
unpickler = Unpickler (strIO)
object2 = unpickler.load ()

print 'object: '+`object`
print 'object2: '+`object`

print object == object2


Hope this helps,
--
Ovidiu Predescu <ovidiu@cup.hp.com>
http://www.geocities.com/SiliconValley/Monitor/7464/
getstate, setstate and pickle [ In reply to ]
I've identified my problem. pickle.py uses map(id,..) as part of its
test routine. I tried to use the same to test. map(id,...) (which
likes sequences) doesn't work on my class instances.

The script below illustrates that dumps(r) ==dumps(loads(dumps(r))) but
that r <> loads(dumps(r)).

My question now moves to: How can I test/verify my pickled data? or is
it that is the dumps match I'm ok? (sound good to me, but are there
traps?)

from pickle import *
class R:
def __init__(self):
self.a = {}
self.b = {}

print r == loads(dumps(r))
print dumps(r) == dumps(loads(dumps(r)))

regards,

--

Emile van Sebille
emile@fenx.com
-------------------
getstate, setstate and pickle [ In reply to ]
Emile van Sebille wrote:
>
> The script below illustrates that dumps(r) ==dumps(loads(dumps(r))) but
> that r <> loads(dumps(r)).

If you haven't given your class a __cmp__ method,
the == will be comparing object references, which
will be different even if the two objects have an
identical structure.

To do a "deep comparison" of two instances, they
need a __cmp__ method which does the appropriate
things -- and so on recursively for any other
objects which are part of the structure.

If you really do want dumps(loads(dumps(r))) to
return a reference to the original r, then you're
out of luck -- pickle won't do that. It will
give you a deep copy of r instead.

Greg