dillというのは、pickleの強化版のようなツールだ。現在使っている変数をまとめて外部のファイルに保存できる。
(バイナリにして保存することを、pickle化、シリアライズ、直列化などと呼ぶらしい)
dillについての情報はネットにあまり書いていない。下記の記事がとても参考になった。
Pythonですべての変数を保存するにはPickleよりdillが便利 - Qiita
余談ですが、「dill pickle」はピクルスの一種を指しているらしく、この語句で検索してもpythonのライブラリは出てきません。検索ワードに「python」を加えましょう。
dill pickle
《料理》ディル・ピクルス◆キュウリをディル(dill)の葉と種と共に塩漬けした物。
dill pickleの意味・用例|英辞郎 on the WEB:アルク
簡単な使い方
公式ドキュメントに使い方が載っていないので、ほぼ上記Qiitaそのままですが。
a = 123
b = 456
c = b - a
string = "Hello World"
import dill
dill.dump_session("session.pkl")
最後の2行で、現在の変数をすべて"session.pkl"というファイルに保存している。
import dill
dill.load_session("session.pkl")
print(a)
print(b)
print(c)
print(string)
'''出力:
123
456
333
Hello World
'''
保存した"session.pkl"から変数を復元し、その値を表示している。
pickleでは保存できないが、dillで保存できる例
上の例では単純な数値や文字列だけを保存(シリアライズ、直列化)した。
しかし、pythonには色々なオブジェクトがあり、pickleでは保存できないものもある。
今回の主題ではないし、私がきちんと理解していないので詳細は省くが、lambda関数、入れ子になった関数などがこれに該当する。dillではpickleを拡張子、lambda関数、入れ子になった関数なども保存できる。
公式の説明では、
12.1. pickle ? Python オブジェクトの直列化 - Python 3.6.5 ドキュメント の中の『12.1.4. pickle 化、非 pickle 化できるもの』
dillのreadme
を参照。
pickleオブジェクトがpickle化できるものの中で比較的、制限されているからです。つまり入れ子関数やlambda、スライスや、その他いろいろなものを処理できません。これらのオブジェクトを直接pickle化したいケースは、それほどはないかもしれませんが、pickle化したい他の物の中に、そういったオブジェクトが出てくることは、かなり一般的です。そのため、pickle化が失敗する原因となるのです。
私が選ぶ2015年の”新しい”Pythonモジュール トップ5 | POSTD
一部、pickle化できない種類のオブジェクトがある。
よく引っかかる例はlambda関数や、openで開いたファイルハンドラで、これが保存するオブジェクトのどこか1箇所にでも使われていると、pickle.dump()がエラーを出す。
pickle [いかたこのたこつぼ]
正規表現のマッチングオブジェクトが入っているとエラーになる
本題に入る。
色々なオブジェクトを保存できるdillだが、正規表現のmatchオブジェクトは保存できない。
import re
result = re.search("lar", "regular expression")
print(result)
print(type(result))
'''出力:
<_sre.SRE_Match object; span=(4, 7), match='lar'>
<class '_sre.SRE_Match'>
'''
"result"というmatchオブジェクトを作った。ではこれをdillで保存してみよう。
dill.dump_session("session2.pkl")
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-5-07b38aa0950a> in <module>()
----> 1 dill.dump_session("session2.pkl")
D:\Code\Anaconda3\lib\site-packages\dill\dill.py in dump_session(filename, main, byref)
331 pickler._recurse = False
332 pickler._session = True
--> 333 pickler.dump(main)
334 finally:
335 f.close()
(長いので中略)
D:\Code\Anaconda3\lib\pickle.py in save(self, obj, save_persistent_id)
494 reduce = getattr(obj, "__reduce_ex__", None)
495 if reduce is not None:
--> 496 rv = reduce(self.proto)
497 else:
498 reduce = getattr(obj, "__reduce__", None)
TypeError: can't pickle _sre.SRE_Match objects
ダメだ。matchオブジェクトは保存できない。
解決方法
今回は、「matchオブジェクトも保存する」のではなく、「matchオブジェクトは保存できなくても良いから、その他のオブジェクトをまとめて保存する」ことを目指す。
つまり解決と言っているのは、具体的には「matchオブジェクト以外を保存する」ことである。
dump_session()関数に「指定した変数は除外する」という引数でも無いかなぁと思ったが、
公式ドキュメントを見てもそういう引数はない。
dill module documentation - dill 0.2.9.dev0 documentation
したがって、変数を削除してからdillを実行することにする。
変数の削除はdel [変数名]で実行できる。
import re
result = re.search("lar", "regular expression")
print(result)
print(type(result))
'''出力:
<_sre.SRE_Match object; span=(4, 7), match='lar'>
<class '_sre.SRE_Match'>
'''
del result
dill.dump_session("session2.pkl")
でresult以外の変数を保存できた。
保存したファイルを使用して変数を表示することもできた。(ソースコードは最初の例のファイル名を変えただけなので特に貼らない)
それでは。