Reputation: 205
I am trying to save and load some classes using pickle. In my project I have some classes with variables containing lists and/or dictionaries and/or tuples of other classes. when I load the saved classes the classes within are different. I found a great tutorial about the static method __new__
here. I made the following code. When the function load is executed I get 3 instances of class 1 and 2 of class2. why?
import pickle
def saveclass(obj):
f = file(obj.name, 'wb')
pickle.dump(obj, f, -1)
f.close()
def loadclass(name):
f = file(name, 'rb')
retclass = pickle.load(f)
f.close()
return retclass
class basicclass(object):
def __new__(cls, *args, **kw):
instances = cls.instances
obj = object.__new__(cls, *args, **kw)
if obj in instances:
return instances[instances.index(obj)]
else:
instances.append(obj)
return obj
class class1(basicclass):
instances = []
def __init__(self, name):
basicclass.__init__(self)
self.name = name
class class2(basicclass):
instances = []
def __init__(self, name, otherclass):
basicclass.__init__(self)
self.name = name
self.otherclass = otherclass
c1 = class1("class1")
c2 = class2("class2", c1)
print c1.name
print c2.name, 'has', c2.otherclass.name
print c2.name, "'s 'inside' class is c1:", c2.otherclass == c1
print "Class1 instances"
for inst in c1.instances:
print inst.name, ':', inst
print "Class2 instances"
for inst in c2.instances:
print inst.name, ':', inst
print 'saving classes'
saveclass(c1)
saveclass(c2)
print 'Resetting classes'
c1 = None
c2 = None
print 'Reloading classes'
c1 = loadclass("class1")
c2 = loadclass("class2")
print c1.name
print c2.name, 'has', c2.otherclass.name
print c2.name, "'s 'inside' class is c1:", c2.otherclass == c1
print "Class1 instances"
for inst in c1.instances:
print inst.name, ':', inst
print "Class2 instances"
for inst in c2.instances:
print inst.name, ':', inst
Output:
> class1
> class2 has class1
> class2 's 'inside' class is c1: True
> Class1 instances
> class1 : <__main__.class1 object at 0xb7302a8c>
> Class2 instances
> class2 : <__main__.class2 object at 0xb7302a2c>
> saving classes
> Resetting classes
> Reloading classes
> class1
> class2 has class1
> class2 's 'inside' class is c1: False
> Class1 instances
> class1 : <__main__.class1 object at 0xb7302a8c>
> class1 : <__main__.class1 object at 0xb72fe10c>
> class1 : <__main__.class1 object at 0xb72fe1ac>
> Class2 instances
> class2 : <__main__.class2 object at 0xb7302a2c>
> class2 : <__main__.class2 object at 0xb72fe18c>
Upvotes: 1
Views: 881
Reputation: 14873
There are two possibilities which come into my mind:
You want to preserve identity when pickling and unpickling. An object of a class which already exists has a special identifier. The object is reused when unpickled, if it already exists. Here is an example which uses __new__
to check whether an object already exists. You can use this with json, too. Problems arise when you have mutable state in the objects. Then loading an old state updates them.
Unpickle and pickle the objects with the same serializer. Do not just use dump
and load
but use the same Pickler
and Unpickler
.
I think this should already be answered somewhere. Maybe you also try to search with "object identity" "serialization" etc. and append the found answers.
Upvotes: 3