Загрузка маринованного объекта в другой файл - ошибка атрибута

У меня возникли проблемы с загрузкой протравленного файла в модуль, отличный от модуля, в котором я запечатлел файл. Мне известна следующая тема: Невозможно загрузить файлы с помощью модулей pickle и multipile. Я попробовал предлагаемое решение импорта класса в модуль, где я распаковываю свой файл, но он продолжает выдавать мне ту же ошибку:AttributeError: Can't get attribute 'Document' on <module '__main__' from ''>

Основная структура того, что я пытаюсь сделать:

Util-файл, который выбирает и удаляет объекты, utils.py:

import pickle

def save_document(doc):

    from class_def import Document

    write_file = open(file_path, 'wb')
    pickle.dump(doc, write_file)

def load_document(file_path):
    from class_def import Document

    doc_file = open(file_path, 'rb')
    return pickle.load(doc_file)

Файл, в котором определен объект Document и вызван метод save util, class_def.py:

import utils

class Document(object):
    data = ""

if __name__ == '__main__':
    doc = Document()
    utils.save_document(doc)

Файл, в котором вызывается метод load util, process.py:

import utils

if __name__ == '__main__':
     utils.load_document(file_path)

Запуск process.py дает упомянутый AttributeError. Если я импортирую файл class_def.py в process.py и запусту его основной метод, как упомянуто в исходном потоке, он будет работать, но я хочу иметь возможность запускать эти два модуля по отдельности, поскольку файл class_def - это этап предварительной обработки, который занимает довольно много времени. когда-то. Как я мог решить это?

2 ответа

Решение

В вашем class_def.py файл у вас есть этот код:

if __name__ == '__main__':
    doc = Document()
    utils.save_document(doc)

Это означает, что doc будет __main__.Document объект, поэтому, когда он маринован, он ожидает, что сможет получить Document класс из основного модуля, чтобы исправить это, вам нужно использовать определение Document из модуля под названием class_def то есть вы бы добавили сюда импорт:

if __name__ == '__main__':
    from class_def import Document 
    # ^ so that it is using the Document class defined under the class_def module
    doc = Document()
    utils.save_document(doc)

таким образом, нужно будет запустить файл class_def.py дважды, один раз как __main__ и как только class_def но это означает, что данные будут засолены как class_def.Document объект, загружающий его, извлечет класс из правильного места. В противном случае, если у вас есть способ создать один объект документа из другого, вы можете сделать что-то подобное в utils.py:

def save_document(doc):
    if doc.__class__.__module__ == "__main__":
        from class_def import Document #get the class from the reference-able module
        doc = Document(doc) #convert it to the class we are able to use


    write_file = open(file_path, 'wb')
    pickle.dump(doc, write_file)

Хотя обычно я предпочитаю первый способ.

У меня была похожая проблема, и я только что понял различия между нашими реализациями.

Ваша файловая структура:

  • util.py
    • определить функции рассола
  • class_def.py
    • утилита импорта
    • определить класс
    • сделать экземпляр
    • позвоните сохранить рассол
  • process.py
    • утилита импорта
    • маринованный груз

Моя ошибка (используя ваши имена файлов) была первой:

  • util_and_class.py
    • определить класс
    • определить функции рассола
    • сделать экземпляр
    • позвоните сохранить рассол
  • process.py
    • import util_and_class
    • вызов загрузки маринада << ОШИБКА

Что решило мою проблему импорта маринадов:

  • util_and_class.py
    • определить класс
    • определить функции рассола
  • pickle_init.py
    • import util_and_class
    • сделать экземпляр
    • позвоните сохранить рассол
  • process.py
    • вызов загрузки

Это имело приятный побочный эффект: мне не нужно было импортировать файл util_and_class, поскольку он запекается в файл pickle. Вызов экземпляра и сохранение рассола в отдельном файле __name__ проблема "загрузки протравленного файла в модуль, отличный от модуля, в котором я запечатлел файл".

Другие вопросы по тегам