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

时间:2016-10-27 14:45:32

标签: python python-3.x pickle

我在一个与我腌制文件的模块不同的模块中加载pickle文件时遇到了一些麻烦。我知道以下帖子:Unable to load files using pickle and multipile modules。我已经尝试了将类导入到模块中的建议解决方案,我将取消我的文件,但它一直给我同样的错误: AttributeError: Can't get attribute 'Document' on <module '__main__' from ''>

我想要做的基本结构:

用于pickles和unpickles对象的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并运行其原始线程中提到的main方法,它可以工作,但我希望能够单独运行这两个模块,因为class_def文件是一个预处理步骤,需要相当一段时间我怎么能解决这个问题?

2 个答案:

答案 0 :(得分:15)

在您的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对象进行pickle所以加载它将从正确的位置检索类。否则,如果你有办法从另一个文档对象构造一个文档对象,你可以在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)

虽然我通常更喜欢第一种方式。

答案 1 :(得分:2)

我遇到了类似的问题,只是意识到我们的实现之间存在差异。

您的文件结构:

  • util.py
    • 定义pickle函数
  • class_def.py
    • import util
    • 定义类
    • make instance
    • 致电保存泡菜
  • process.py
    • import util
    • 装载泡菜

我的错误(使用您的文件名)是第一次:

  • util_and_class.py
    • 定义类
    • 定义pickle funcs
    • make instance
    • 致电保存泡菜
  • process.py
    • import util_and_class
    • call load pickle&lt;&lt; ERROR

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

  • util_and_class.py
    • 定义类
    • 定义pickle funcs
  • pickle_init.py
    • import util_and_class
    • make instance
    • 致电保存泡菜
  • process.py
    • call load pickle

这有一个受欢迎的副作用,我不需要导入util_and_class文件,因为它被烘焙到pickle文件中。调用实例并将pickle保存在单独的文件中解决了{em>“问题的__name__问题”在与我腌制文件的模块不同的模块中加载pickle文件。“