ellipse-of-uncertainty
ellipse-of-uncertainty

Reputation: 1035

Why can't pickle a list that is an attribute of an object?

I am trying to pickle an instance of a custom class, this class has an attribute called "widgets" that contains a list of widget object. When I pickle my container the list is lost. Is it not possible to pickle a list within an object?

import pickle

filename = 'container.pkl'

class Container(object):
    widgets = []

class Widget(object):
    pass

c = Container()
c.name = "My Container"

w = Widget()
w.name = "My Widget"

c.widgets.append(w)

data = open(filename, 'wb')
pickle.dump(c, data)
data.close()

Later I try to unpickle...

# assume I have imported the classes and filename here

data = open(filename, 'rb')
container = pickle.load(data)
data.close()


print container.name # shows the pickled name
print container.widgets # shows []

I have tried pickle and cPickle with the same results.

Upvotes: 2

Views: 4476

Answers (3)

Viktor Kerkez
Viktor Kerkez

Reputation: 46626

widgets is an attribute of the class Container not an attribute of the instance of the Container class. When you pickled the instance you haven't pickled the class attributes, just the instance attributes. So when you unpickle it you get just the instance attributes back.

You should read about instance vs. class attributes in the python docs

If you want to pickle the widgets too, then you should make the list an instance attribute instead of a class attribute. Here is an example:

import pickle

filename = 'container.pkl'

class Container(object):
    def __init__(self, name):
        self.name = name
        self.widgets = []

class Widget(object):
    def __init__(self, name):
        self.name = name

c = Container('My Container')
w = Widget('My Widget')

c.widgets.append(w)

data = open(filename, 'wb')
pickle.dump(c, data)
data.close()

Upvotes: 8

tdelaney
tdelaney

Reputation: 77387

The problem is that widgets is a class attribute and wasn't pickled. The script will appear to work if you unpickle in the same session because Container.widgets is already what you want. It will not work when you start a new session because the Container.widgets will not have been populated.

Upvotes: 0

Prahalad Deshpande
Prahalad Deshpande

Reputation: 4767

It is definitely possible to pickle List objects within Python. It is possible that the custom class you are using may have overridden the __getstate__ and __setstate__ methods, where-in the developer has decided not to pickle the widget list by deleting it from the set of attributes to be pickled/un-pickled for that class.

Refer here for more information. It would be good if you can observe the source code for this custom class and check if this indeed the case

Upvotes: 0

Related Questions