(質問に直接ジャンプして、さらに下に移動し、紹介をスキップすることができます。)
ユーザー定義クラスからPythonオブジェクトを選択することには、一般的な問題があります。
# This is program dumper.py
import pickle
class C(object):
pass
with open('obj.pickle', 'wb') as f:
pickle.dump(C(), f)
実際、別のプログラムからオブジェクトを取り戻そうとするとloader.py
、
# This is program loader.py
with open('obj.pickle', 'rb') as f:
obj = pickle.load(f)
結果は
AttributeError: 'module' object has no attribute 'C'
実際、クラスは名前( "C")でピクルスにされており、loader.py
プログラムは。について何も知りませんC
。一般的な解決策は、
from dumper import C # Objects of class C can be imported
with open('obj.pickle', 'rb') as f:
obj = pickle.load(f)
ただし、このソリューションには、ピクルス化されたオブジェクトによって参照されるすべてのクラスをインポートする必要があるという事実を含む、いくつかの欠点があります(多くの場合があります)。さらに、ローカル名前空間はdumper.py
プログラムからの名前によって汚染されます。
現在、これに対する解決策は、ピクルスにする前に完全に修飾されたオブジェクトで構成されています。
# New dumper.py program:
import pickle
import dumper # This is this very program!
class C(object):
pass
with open('obj.pickle', 'wb') as f:
pickle.dump(dumper.C(), f) # Fully qualified class
上記の元のloader.py
プログラムでの選択解除が直接機能するようになりました(実行する必要はありませんfrom dumper import C
)。
質問:さて、からの他のクラスはdumper.py
、ピクルスにすると自動的に完全に修飾されるようです。これがどのように機能するか、そしてこれが信頼できる文書化された動作であるかどうかを知りたいです。
import pickle
import dumper # This is this very program!
class D(object): # New class!
pass
class C(object):
def __init__(self):
self.d = D() # *NOT* fully qualified
with open('obj.pickle', 'wb') as f:
pickle.dump(dumper.C(), f) # Fully qualified pickle class
現在、元のloader.py
プログラムでの選択解除も機能します(行う必要はありませんfrom dumper import C
)。完全に資格print obj.d
のあるクラスを提供しますが、これは驚くべきことです。
<dumper.D object at 0x122e130>
この動作は非常に便利です。これは、一番上のピクルスオブジェクトのみがモジュール名(dumper.C()
)で完全に修飾されている必要があるためです。しかし、この動作は信頼でき、文書化されていますか?クラスが名前( "D")でピクルスにされているのに、ピクルス解除されたself.d
属性がクラスdumper.D
(一部のローカル D
クラスではない)であると判断されるのはなぜですか?
PS:質問、洗練された:この質問への答えを示すかもしれないいくつかの興味深い詳細に気づきました:
ピクルスプログラムdumper.py
では、最初のプログラム(なしのプログラム)で、をprint self.d
印刷します。一方、inを使用してオブジェクトを実行および作成すると、 printが作成されます。属性はPythonによって自動的に修飾されます。したがって、モジュールは、上記の優れたピッキング解除動作には何の役割も果たさないようです。<__main__.D object at 0x2af450>
dumper.py
import dumper
import dumper
dumper.C()
dumper.py
print self.d
<dumper.D object at 0x2af450>
self.d
pickle
したがって、問題は本当にです。2番目のケースでは、なぜPythonD()
が完全修飾に変換されるのでしょうか。dumper.D
これはどこかに文書化されていますか?