13.1.5.3 外部オブジェクトの pickle 化および unpickle 化

オブジェクトの永続化を便利にするために、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() メソッドと共に使われます。



脚注

... 上のユーザ定義関数にゆだねます13.7
ユーザ定義関数に関連付けを行うための実際のメカニズムは、 pickle および cPickle では少し異なります。 pickle のユーザは、サブクラス化を行い、 persistend_id() および persistent_load() メソッドを上書きすることで同じ効果を得ることができます
... ことができるようにするために存在しています13.8
Guide と Jim が居間に座り込んでピクルス (pickles) を 嗅いでいる光景を想像してください。
ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。