Reputation: 8429
I would like to implement a class (ideally a singleton) for which the state should be restored using cPickle mechanism at initialization stage. To do so I wrote the following snippet:
import cPickle
import collections
class Test(collections.OrderedDict):
path = "test.cp"
def __init__(self):
self.path = "test.cp"
collections.OrderedDict.__init__(self)
try:
f = open(Test.path,"rb")
except IOError:
return
else:
ud = cPickle.load(f)
self.update(ud)
f.close()
def save(self):
f = open(Test.path,"wb")
cPickle.dump(self,f)
f.close()
if __name__ == "__main__":
t = Test()
t.save()
t1 = Test()
Running that snippet produces the following error:
Traceback (most recent call last):
File "C:\Documents and Settings\pellegrini\Bureau\test.py", line 31, in <module>
t1 = Test()
File "C:\Documents and Settings\pellegrini\Bureau\test.py", line 18, in __init__
ud = cPickle.load(f)
TypeError: ('__init__() takes exactly 1 argument (2 given)', <class '__main__.Test'>, ([],))
When inheriting from a dict
instead of a collections.OrderedDict
this works. From other similar posts, this may have something to do with __reduce__
method but I do not understand why and how ?
Would you have any idea about how to solve this problem ?
thanks a lot
Eric
Upvotes: 1
Views: 379
Reputation: 14873
I guess that the OrderedDict has its own way of serialization.
def __init__(self, *args):
self.path = "test.cp"
collections.OrderedDict.__init__(self, *args)
try this and you get a recursion problem because pickle uses __init__
.
An error free solution is:
import cPickle
import collections
class Test(collections.OrderedDict):
path = "test.cp"
def __init__(self, *args):
self.path = "test.cp"
collections.OrderedDict.__init__(self, *args)
if not args:
try:
f = open(Test.path,"rb")
except IOError:
return
else:
ud = cPickle.load(f)
self.update(ud)
f.close()
def save(self):
with open(Test.path,"wb") as f:
cPickle.dump(self,f)
if __name__ == "__main__":
t = Test()
t.save()
t1 = Test()
Singleton
import pickle
import collections
_Test_singleton = None
class Test(collections.OrderedDict):
path = "test.cp"
def __new__(self, *args, **kw):
global _Test_singleton
if _Test_singleton is not None:
return _Test_singleton
_Test_singleton = collections.OrderedDict.__new__(self, *args, **kw)
_Test_singleton.load()
return _Test_singleton
def __init__(self, *args):
collections.OrderedDict.__init__(self, *args)
def load(self):
try:
f = open(self.path,"rb")
except IOError:
return
else:
try:
ud = pickle.load(f)
finally:
f.close()
self.update(ud)
def save(self):
with open(self.path,"wb") as f:
pickle.dump(self,f)
if __name__ == "__main__":
t = Test()
t.save()
t1 = Test()
assert t is t1
Upvotes: 3