Yannis
Yannis

Reputation: 205

Saving and loading classes in python

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

Answers (1)

User
User

Reputation: 14873

There are two possibilities which come into my mind:

  1. 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.

  2. 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

Related Questions