銀月の符号

Python 使い見習いの日記・雑記

pickle できない属性をもつクラスへの対策例

urllib2.OpenerDirector オブジェクトを属性に持ったクラスオブジェクトを pickle 化しようとしたがエラーがでて足踏みさせられたのでメモ。ほぼライブラリリファレンスのままなのだけれど。

まず、 __getstate__ メソッドを定義する。これは pickle 化する際に用いられる。状態を保持するオブジェクトを返すようにする必要がある。ここではリファレンスの例にしたがって self.__dict__ から pickle 化できない属性を取り除いたものにした。

次に __setstate__ メソッドを定義する。これは unpickle 化する際に用いられ、第1引数には __getstate__ の戻り値が収まる。受け取った引数の情報を使ってクラスオブジェクトを再現するための処理を行う必要がある。ここでは自身の属性を元と同義とみなせるようにいじってしまえば OK。

import urllib2
class Flv(object):
    def __init__(self):
        self.opener = urllib2.build_opener()
        # 略

    # 略

    def __getstate__(self):
        odict = self.__dict__.copy()
        del odict['opener'] # pickle 時に保存しないよう、消してしまう
        return odict

    def __setstate__(self, odict):
        self.__dict__.update(odict)
        self.opener = urllib2.build_opener() # unpickle 時、作り直す

ちなみにリファレンスの該当部分は http://www.python.jp/doc/release/lib/pickle-example.html で、ファイルオブジェクトをもったクラスの例が書かれている。pickle モジュールのリファレンスにはそのほかにもさまざまな項目があったが情報密度が高めで吸収しきれず。必要になったときに読みなおそうっと。