I'm using a dictionary to store objects. The dictionary is then stored in a shelf file. When retrieving the dictionary from the shelf file for printing stuff, it gets an error.
The following script is to creat a shelf file for testing:
# creating shelf file for testing
import shelve
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
buddy = Dog("Buddy", 9)
miles = Dog("Miles", 4)
d = {}
d['buddy'] = buddy
d['miles'] = miles
with shelve.open('dogs') as sf:
sf['d'] = d
Then, the following script reads the shelf file created above:
# reading shelf file and printing stuff
import shelve
with shelve.open('dogs') as sf:
d = sf['d']
for k in d.keys():
print(d[k].name, d[k].age)
After running the above script, it gets the following error message:
Traceback (most recent call last):
File "C:\Users\jc\AppData\Local\Programs\Python\Python39\lib\shelve.py", line 111, in __getitem__
value = self.cache[key]
KeyError: 'd'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "c:\Users\jc\OneDrive\Documents\PythonScripts\test2.py", line 23, in <module>
d = sf['d']
File "C:\Users\jc\AppData\Local\Programs\Python\Python39\lib\shelve.py", line 114, in __getitem__
value = Unpickler(f).load()
AttributeError: Can't get attribute 'Dog' on <module '__main__' from 'c:\\Users\\jc\\OneDrive\\Documents\\PythonScripts\\test2.py'>
The problem is that the script that reads the saved shelf doesn't know the definition of the Dog
class.
shelve
is based on the pickle
module. pickle
can serialize instances of classes, but it doesn't serialize the class itself. The class definition must exist in the module that reads the shelved data.
To quote the documentation:
pickle can save and restore class instances transparently, however the class definition must be importable and live in the same module as when the object was stored.
If you make sure the definition of Dog
is available in the script before reading the shelf, the saved data will load correctly.