在不同文件中加载腌制对象 - 属性错误

Load pickled object in different file - Attribute error

我在将腌制文件加载到与我腌制文件所在的模块不同的模块中时遇到了一些问题。我知道以下线程:。我已经尝试了将 class 导入到我正在解压我的文件的模块中的建议解决方案,但它一直给我同样的错误: AttributeError: Can't get attribute 'Document' on <module '__main__' from ''>

我要做的事情的基本结构:

pickle 和 unpickle 对象的 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 文件是一个预处理步骤,需要相当长的时间。我该如何解决这个问题?

在您的 class_def.py 文件中,您有以下代码:

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

这意味着 doc 将是一个 __main__.Document 对象,所以当它被 pickle 时,它​​期望能够从 main 中得到一个 Document class模块,要解决此问题,您需要使用名为 class_def 的模块中 Document 的定义,这意味着您将在此处添加导入:

(一般来说,您可以在 if __name__ == "__main__" 中执行 from <own module name> import *

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 但这确实意味着数据将被 pickle作为 class_def.Document 对象,因此加载它将从正确的位置检索 class。否则,如果您有一种从另一个文档对象构造一个文档对象的方法,您可以在 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
    • 定义 pickle 函数
  • class_def.py
    • 导入实用程序
    • 定义class
    • 创建实例
    • 调用保存 pickle
  • process.py
    • 导入实用程序
    • 加载 pickle

我的错误(使用你的文件名)首先是:

  • util_and_class.py
    • 定义class
    • 定义 pickle 函数
    • 创建实例
    • 调用保存 pickle
  • process.py
    • 进口util_and_class
    • 调用加载 pickle << 错误

是什么解决了我的 pickle 导入问题:

  • util_and_class.py
    • 定义class
    • 定义 pickle 函数
  • pickle_init.py
    • 进口util_and_class
    • 创建实例
    • 调用保存 pickle
  • process.py
    • 调用负载 pickle

这有一个受欢迎的副作用,即我不需要导入 util_and_class 文件,因为它已烘焙到 pickle 文件中。调用实例并将 pickle 保存在单独的文件中解决了 "loading a pickled file in a module that is different from the module where I pickled the file."

__name__ 问题