【问题标题】:Load pickled object in different file - Attribute error在不同的文件中加载腌制对象 - 属性错误
【发布时间】:2017-03-10 07:37:39
【问题描述】:

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

我正在尝试做的基本结构:

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

【问题讨论】:

  • 没有回答您的问题,但您应该在打开文件处理程序后关闭它们,或者直接使用with
  • 当文件以__main__ 运行时,其中定义的任何内容都将作为__main__ 模块的成员腌制,因此如果您随后加载到不同的文件中,它将失败。您只需要从模块中挑选东西,然后 __main__ 最快的修复是 from &lt;this modules name&gt; import * 但我不建议在生产代码中使用它。
  • namespace on python pickle 的可能重复项,但我认为可能有更好的线程标记为 dup
  • 检查这个线程stackoverflow.com/a/51397373/7429675,你可以这样做

标签: python python-3.x pickle


【解决方案1】:

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

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

这意味着doc 将是一个__main__.Document 对象,因此当它被腌制时,它期望能够从主模块中获得一个Document 类,要解决这个问题,您需要使用定义Document 来自名为 class_def 的模块,这意味着您将在此处添加导入:

(一般来说,你可以在if __name__ == "__main__" 里面做from &lt;own module name&gt; 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,但这确实意味着数据将被腌制为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)

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

【讨论】:

  • 惊人的答案!
【解决方案2】:

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

您的文件结构:

  • util.py
    • 定义泡菜函数
  • class_def.py
    • 导入实用程序
    • 定义类
    • 制作实例
    • 调用保存泡菜
  • process.py
    • 导入实用程序
    • 加载泡菜

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

  • util_and_class.py
    • 定义类
    • 定义泡菜函数
    • 制作实例
    • 调用保存泡菜
  • process.py
    • 导入 util_and_class
    • 调用加载pickle

什么解决了我的泡菜导入问题:

  • util_and_class.py
    • 定义类
    • 定义泡菜函数
  • pickle_init.py
    • 导入 util_and_class
    • 制作实例
    • 调用保存泡菜
  • process.py
    • 调用加载泡菜

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-18
    • 2018-08-21
    • 1970-01-01
    • 2021-11-10
    • 2018-02-04
    • 1970-01-01
    相关资源
    最近更新 更多