How to pickle yourself?
This is what I ended up doing. Updating the __dict__
means we keep any new member variables I add to the class and just update the ones that were there when the object was last pickle'd. It seems the simplest while maintaining the saving and loading code inside the class itself so calling code just does an object.save().
def load(self):
f = open(self.filename, 'rb')
tmp_dict = cPickle.load(f)
f.close()
self.__dict__.update(tmp_dict)
def save(self):
f = open(self.filename, 'wb')
cPickle.dump(self.__dict__, f, 2)
f.close()
The dump part should work as you suggested. for the loading part, you can define a @classmethod that loads an instance from a given file and returns it.
@classmethod
def loader(cls,f):
return cPickle.load(f)
then the caller would do something like:
class_instance = ClassName.loader(f)
If you want to have your class update itself from a saved pickle… you pretty much have to use __dict__.update
, as you have in your own answer. It's kind of like a cat chasing it's tail, however… as you are asking the instance to essentially "reset" itself with prior state.
There's a slight tweak to your answer. You can actually pickle self
.
>>> import dill
>>> class Thing(object):
... def save(self):
... return dill.dumps(self)
... def load(self, obj):
... self.__dict__.update(dill.loads(obj).__dict__)
...
>>> t = Thing()
>>> t.x = 1
>>> _t = t.save()
>>> t.x = 2
>>> t.x
2
>>> t.load(_t)
>>> t.x
1
I used loads
and dumps
instead of load
and dump
because I wanted the pickle to save to a string. Using load
and dump
to a file also works.
And, actually, I can use dill
to pickle an class instance to a file, for later use… even if the class is defined interactively. Continuing from above...
>>> with open('self.pik', 'w') as f:
... dill.dump(t, f)
...
>>>
then stopping and restarting...
Python 2.7.10 (default, May 25 2015, 13:16:30)
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> with open('self.pik', 'r') as f:
... t = dill.load(f)
...
>>> t.x
1
>>> print dill.source.getsource(t.__class__)
class Thing(object):
def save(self):
return dill.dumps(self)
def load(self, obj):
self.__dict__.update(dill.loads(obj).__dict__)
>>>
I'm using dill
, which is available here: https://github.com/uqfoundation