Pythonのpickleを使うと、いろいろなデータを保存出来て便利ですよね。
しかし、ファイルオブジェクトやlambda関数を含むようなオブジェクトを保存するときにはエラーが出てしまいます。
例えばlambda関数を使う例として、defaultdictを保存しようとする例を挙げます。
>>> from collections import defaultdict >>> d = defaultdict(lambda:0) >>> import pickle >>> pickle.dumps(d) Traceback (most recent call last): File "<stdin>", line 1, in <module> _pickle.PicklingError: Can't pickle <function <lambda> at 0x7f3d780b6e18>: attribute lookup <lambda> on __main__ failed
ここでは、辞書にないキーを参照すると「0」を返すような辞書”d”を、lambda関数を使って作成しています。
これをpickle.dumpを用いてシリアライズすると、上のようなエラーが出てしまいます。
また、ファイルなどを読み込んでdumpしようとすると、Type:Errorが出てしまいます。
dillを使って保存する。
そんな時にはdillを使って保存しましょう!
dillはpickleと全く同じ使い方ができる上に、pickleで保存できないようなオブジェクトを保存することができます。
普段からpickleを使っている方であれば、pickleを単純にdillに置き換えるだけで上記のようなエラーを回避することができます。
dillはpipを使って以下のようにインストールすることができます。
$ pip install dill
dillで保存
dillでの保存にはdill.dumpを使用します。
使い方は以下の通りです。
dill.dump(保存する変数, open(保存するパス,’wb’))
実際に保存する手続きを以下に示します。
上で作成した辞書”d”を保存します。
>>> import dill >>> dill.dump(d, open('dictionary.dill','wb'))
上の例では、defaultdictで作成した辞書を’dictionary.dill’という名前で保存しています。
pickleの時とは違い、エラーが出ずに保存ができていることを確認してください。
また、このときopenのオプションを”wb”とすることに注意してください。
ちなみに、wbはバイナリを保存するオプションで、dumpsでは一度辞書をバイナリに変換してから保存を行います。
実際に保存されるバイナリは、dumpsを用いて確認することができます。
>>> dill.dumps(d) b'\x80\x03ccollections\ndefaultdict\nq\x00cdill.dill\n_create_function\nq\x01(cdill.dill\n_load_type\nq\x02X\x08\x00\x00\x00CodeTypeq\x03\x85q\x04Rq\x05(K\x00K\x00K\x00K\x01KCC\x04d\x01S\x00q\x06NK\x00\x86q\x07))X\x07\x00\x00\x00<stdin>q\x08X\x08\x00\x00\x00<lambda>q\tK\x01C\x00q\n))tq\x0bRq\x0cc__builtin__\n__main__\nh\tNN}q\rtq\x0eRq\x0f\x85q\x10Rq\x11.'
出力の先頭には、バイナリ文字列を表すbが付与されていることを確認してください。
dillで読み込み
dillでの読み込みも、pickle同様に行うことができます。
先ほど保存したdictionary.dillを読み込むときは、以下のようにします。
>>> d = dill.load(open('dictionary.dill','rb'))
ここで、openのオプションを「rb」にすることを忘れないようにしてください。
rbはバイナリを読み込むオプションで、loadはバイナリをもとのオブジェクトに復元する働きを持っています。
dumpsと同様、バイナリを直接読み込むloads(loadではないことに注意!)についても確認します。
>>> d_binary = dill.dumps(d) # バイナリ化 >>> d2 = dill.loads(d_binary) # バイナリを復元 >>> d==d2 True
dumpsで辞書をバイナリ化した後、loadsで復元できていることが確認できます。
あまり使わないかもしれませんが、挙動を確認しておくことは大事ですよね!