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

lma*_*ens 20 python pickle python-3.x

我在一个模块中加载一个pickle文件时有些麻烦,该模块与我腌制文件的模块不同.我知道以下线程:无法使用pickle和multipile模块加载文件.我已经尝试了将类导入到模块中的建议解决方案,我正在取消我的文件,但它一直给我同样的错误: AttributeError: Can't get attribute 'Document' on <module '__main__' from ''>

我想要做的基本结构:

Util文件,用于pickles和unpickles对象,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)
Run Code Online (Sandbox Code Playgroud)

文件定义了Document对象并调用了save util方法,class_def.py:

import utils

class Document(object):
    data = ""

if __name__ == '__main__':
    doc = Document()
    utils.save_document(doc)
Run Code Online (Sandbox Code Playgroud)

调用load util方法的文件,process.py:

import utils

if __name__ == '__main__':
     utils.load_document(file_path)
Run Code Online (Sandbox Code Playgroud)

运行process.py会给出上面提到的AttributeError.如果我将class_def.py文件导入process.py并运行其原始线程中提到的main方法,它可以工作,但我希望能够单独运行这两个模块,因为class_def文件是一个预处理步骤,需要相当一段时间 我该怎么解决这个问题?

Tad*_*sen 18

在你的class_def.py文件中你有这个代码:

if __name__ == '__main__':
    doc = Document()
    utils.save_document(doc)
Run Code Online (Sandbox Code Playgroud)

这意味着doc它将成为一个__main__.Document对象,所以当它被pickle时,它希望能够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)
Run Code Online (Sandbox Code Playgroud)

这样它将需要运行class_def.py文件两次,一次as from <own module name> import *和一次,if __name__ == "__main__"但它确实意味着数据将被腌制为一个__main__对象,所以加载它将从正确的位置检索类.否则,如果你有办法从另一个文档对象构造一个文档对象,你可以在class_def以下方面做这样的事情:

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)
Run Code Online (Sandbox Code Playgroud)

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