web-dev-qa-db-ja.com

別のファイルにピクルスされたオブジェクトをロード-属性エラー

ファイルをピクルしたモジュールとは異なるモジュールにピクルしたファイルをロードするのに問題があります。私は次のスレッドを知っています: pickleおよびmultipileモジュールを使用してファイルをロードできません 。クラスをファイルの選択を解除するモジュールにインポートする提案されたソリューションを試しましたが、同じエラーが表示され続けます:AttributeError: Can't get attribute 'Document' on <module '__main__' from ''>

私がやろうとしていることの基本構造:

オブジェクトのピクルスとピクルス解除を行う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ファイルは前処理ステップであり、しばらくして。どうすればこれを解決できますか?

18
lmartens

class_def.pyファイルには次のコードがあります。

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

これは、doc__main__.Documentオブジェクトになることを意味します。したがって、それをピクルスすると、メインモジュールからDocumentクラスを取得できることが期待されます。 class_defというモジュールのDocumentの定義を使用するには、ここにインポートを追加します。

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ファイルを2回実行する必要があります。1回は__main__として、もう1回はclass_defとして1回です。ただし、データは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)

通常、私は最初の方法を好むでしょう。

17

私は同様の問題を抱えていましたが、実装の違いを認識しただけです。

ファイル構造:

  • util.py
    • ピクル関数を定義する
  • class_def.py
    • インポートユーティリティ
    • クラスを定義する
    • インスタンスを作る
    • 保存ピクルを呼び出します
  • process.py
    • インポートユーティリティ
    • ロードピクルス

ファイル名を使用して)私の間違いは最初でした:

  • util_and_class.py
    • クラスを定義する
    • ピクルファンクを定義する
    • インスタンスを作る
    • 保存ピクルを呼び出します
  • process.py
    • util_and_classをインポート
    • ロードピクルの呼び出し<<エラー

ピクルのインポートの問題を解決した理由:

  • util_and_class.py
    • クラスを定義する
    • ピクルファンクを定義する
  • pickle_init.py
    • util_and_classをインポート
    • インスタンスを作る
    • 保存ピクルを呼び出します
  • process.py
    • ロードピクルの呼び出し

これには、util_and_classファイルがpickleファイルに焼き付けられているため、インポートする必要がないという歓迎すべき副作用がありました。インスタンスを呼び出して、ピクルを別のファイルに保存すると、__name__ issue of "ファイルをピクルしたモジュールとは異なるモジュールにピクルされたファイルをロードする。"

2
xtian