オブジェクトの永続化を便利にするために、pickle は pickle 化されたデータ列上にないオブジェクトに対して参照を 行うという概念をサポートしています。これらのオブジェクトは ``永続化 id (persistent id)'' で参照されており、この id は 単に印字可能な ASCII 文字からなる任意の文字列です。 これらの名前の解決方法は pickle モジュールでは定義されて いません; オブジェクトはこの名前解決を pickler および unpickler 上のユーザ定義関数にゆだねます 13.7。
外部永続化 id の解決を定義するには、pickler オブジェクトの persistent_id 属性と、 unpickler オブジェクトの persistent_load 属性を設定する必要があります。
外部永続化 id を持つオブジェクトを pickle 化するには、pickler
は自作の persistent_id() メソッドを
持たなければなりません。このメソッドは一つの引数をとり、
None
とオブジェクトの永続化 id のうちどちらかを
返さなければなりません。None
が返された場合、
pickler は単にオブジェクトを通常のように pickle 化するだけ
です。永続化 id 文字列が返された場合、 piclkler はその
文字列に対して、、unpickler がこの文字列を永続化 id として
認識できるように、マーカと共に pickle 化します。
外部オブジェクトを unpickle 化するには、unpickler は自作の persistent_load() 関数を持たなければなりません。 この関数は永続化 id 文字列を引数にとり、参照されているオブジェクト を返します。
多分 より理解できるようになるようなちょっとした 例を以下に示します:
import pickle from cStringIO import StringIO src = StringIO() p = pickle.Pickler(src) def persistent_id(obj): if hasattr(obj, 'x'): return 'the value %d' % obj.x else: return None p.persistent_id = persistent_id class Integer: def __init__(self, x): self.x = x def __str__(self): return 'My name is integer %d' % self.x i = Integer(7) print i p.dump(i) datastream = src.getvalue() print repr(datastream) dst = StringIO(datastream) up = pickle.Unpickler(dst) class FancyInteger(Integer): def __str__(self): return 'I am the integer %d' % self.x def persistent_load(persid): if persid.startswith('the value '): value = int(persid.split()[2]) return FancyInteger(value) else: raise pickle.UnpicklingError, 'Invalid persistent id' up.persistent_load = persistent_load j = up.load() print j
cPickle モジュール内では、 unpickler の persistent_load 属性は Python リスト型として設定することができます。この場合、 unpickler が永続化 id に遭遇しても、永続化 id 文字列は単にリストに 追加されるだけです。この仕様は、pickle データ中の全てのオブジェクトを 実際にインスタンス化しなくても、 pickle データ列中でオブジェクトに対する 参照を ``嗅ぎ回る'' ことができるようにするために存在しています 13.8。 リストに persistent_load を設定するやり方は、 よく Unpickler クラスの noload() メソッドと共に使われます。