Почему я не могу сохранить в файле на полке словарь, в котором хранятся объекты?

#python #shelve

Вопрос:

Я использую словарь для хранения объектов. Затем словарь сохраняется в файле на полке. При извлечении словаря из файла полки для печати материалов появляется ошибка.

Следующий сценарий предназначен для создания файла полки для тестирования:

 # 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
 

Затем следующий сценарий считывает файл полки, созданный выше:

 # 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)
 

После запуска приведенного выше сценария он получает следующее сообщение об ошибке:

 Traceback (most recent call last):
  File "C:UsersjcAppDataLocalProgramsPythonPython39libshelve.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:UsersjcOneDriveDocumentsPythonScriptstest2.py", line 23, in <module>
    d = sf['d']
  File "C:UsersjcAppDataLocalProgramsPythonPython39libshelve.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'>
 

Ответ №1:

Проблема в том, что скрипт, который считывает сохраненную полку, не знает определения Dog класса.

shelve основан на pickle модуле. pickle может сериализовать экземпляры классов, но не сериализует сам класс. Определение класса должно существовать в модуле, который считывает отложенные данные.

Чтобы процитировать документацию:

pickle может прозрачно сохранять и восстанавливать экземпляры классов, однако определение класса должно быть импортируемым и находиться в том же модуле, что и при хранении объекта.

Если вы убедитесь, что определение Dog доступно в сценарии перед чтением полки, сохраненные данные будут загружены правильно.