Hey,

Does anyone know how to pickle classes that have classes within them? I get back the top level attributes, but not the attributes under them.

For instance:

import pickle

class authorObj():
    class authors():
        pass

q = authorObj()
q.authors.name = 'somebody'

output = open('test.pkl', 'wb')
pickle.dump(q, output)
output.close()

gives me no error

but when i try to unpickle the data, I lose the attributes under author (the top level attribute)

>>> pkl_file = open('test.pkl', 'rb')
>>> q = pickle.load(pkl_file)
>>> pkl_file.close()
>>> q.authors.t
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    q.authors.t
AttributeError: class authors has no attribute 't'

Does anyone know how to save such an object?

Thanks!

Recommended Answers

All 5 Replies

Only the class instance is pickled, the class structure needs to be coded in the new program again:

import pickle

# this class structure also has to be coded in another
# program, if you want to load the pickle file there
class authorObj():
    class authors():
        pass


q = authorObj()
q.authors.name = 'somebody'

output = open('test.pkl', 'w')
pickle.dump(q, output)
output.close()

# now load again as instance q1

input = open('test.pkl', 'r')
q1 = pickle.load(input)
input.close()

print q1.authors.name  # somebody

Hi,

I have tried this, but it does not work. I commented out the top part which does the pickling and focused on the unpickling:

import pickle

# now load again as instance q1
input = open('test.pkl', 'r')
q1 = pickle.load(input)
input.close()
print q1.authors.name  # somebody

>>> Traceback (most recent call last):
  File "C:\Documents and Settings\Your Name\Desktop\python stuff\testClass.py", line 21, in <module>
    print q1.authors.name  # somebody
AttributeError: class authors has no attribute 'name'

I get the same error. The attribute one level deeper is lost.

Also, I am not sure what you mean when you say:

# this class structure also has to be coded in another
# program, if you want to load the pickle file there

Do you mean it can't be in the same script?

Thanks again!

Your class is unusual in that it is nested and does not contain any constructor. Normally constructed class is pickled this way. Dump:

# part 1 -- using module pickle with a class
# (after dumping the pickle file run part 2)

import pickle

# this class structure also has to be coded in another
# program, if you want to load the pickle file there
class authorObj():
    def __init__(self):
        pass


q = authorObj()
q.name = 'John Smith'
q.job = 'painter'

output = open('test.pkl', 'w')
pickle.dump(q, output)
output.close()

Load:

# part 2 -- using module pickle with a class
# (run part 1 first to create the pickle file)

import pickle

# needs same class structure for pickle file load
# that you used for pickle file dump
class authorObj():
    def __init__(self):
        pass


# now load again as instance q1
input = open('test.pkl', 'r')
q1 = pickle.load(input)
input.close()

print q1.name  # John Smith
print q1.job   # painter

Thanks.

Having objects within objects makes it much easier for me to find and organizing my data. However, it's not very useful if it can't save it correctly. Is there any way to do it?

You may have to use class methods __getstate__ and __setstate__ to pickle your type of class correctly.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.