PythonでプログラミングをしているときにPythonオブジェクトを保存したいというときってありませんか?
そんな時、オブジェクトを保存・復元するのに便利な標準ライブラリがpickleです。
pickleはPythonオブジェクトの直列化(シリアライズ)や非直列化(デシリアライズ)を扱うライブラリです。
平たく言うと、Pythonオブジェクトをファイルとして保存し、呼び出せるようにすることができる形にするためのライブラリという事になります。
この記事では、そんなpickleについて以下の内容で解説していきます!
【基礎】pickleとは何か
【基礎】直列化(Serialize,シリアライズ)とは何か
【発展】pickleでファイルを保存
【発展】pickleファイルの復元
【発展】pickleファイルが復元できないときの対策
といった具体的な使い方についても解説していきます。
今回は、Pythonの標準ライブラリであるpickleを使ってPythonオブジェクトのファイル保存、および復元についてわかりやすく解説していきます。
本記事を読む前に、Pythonがどんなプログラミング言語なのかをおさらいしておきたい人は次の記事を参考にしてください。
→ Pythonとは?特徴やできること、活用例をわかりやすく簡単に解説
なお、その他のPythonの記事についてはこちらにまとめています。
pickleとは
pickleとはPythonオブジェクトの直列化、非直列化を通じてオブジェクトの状態を保存し復元するためのライブラリです。
語源はpickle(日本語ではピクルスという複数形で有名ですね)から来ており、塩漬けや酢漬けのように状態を保存し、その状態から取り出されることからpickleという名前が付けられています。
直列化(selialize)という言葉自体あまり日常生活では使わない言葉ですので、簡単に説明すると、オブジェクトをバイト列などに変換した上で状態を維持することを指します。それをファイルとして保存することで別の場所からでもそれを呼び出せるようになります。
非直列化(deserialize)はその逆で、バイト列などに変換されたオブジェクトを元の形に復元することです。
バイト列はバイト型のデータを列として並べたものです。
バイト型とは数値型や文字列型、画像データなどのもととなっている最小のデータ型で、様々なデータ型を共通の形で保存できるデータ型です。
ファイル形式等を気にせず汎用的に使用できるデータ形式のため、pickle化を行う際にはバイト型の使用をおすすめします。
pickleでは変換方法としてバイナリデータとして保存する方法とテキストデータとして保存する方法があります
Pythonオブジェクトをバイナリデータ等に変換、保存することにより別の場所、別のタイミングでそのオブジェクトを復元させることがpickleの使い道です。
pickleでファイル保存
pickleでPythonオブジェクトをファイルとして保存する前に一つ注意点があります。それはファイルをバイナリデータとして保存するかテキストデータとして保存するのかという点です。
これはpickleでオブジェクトを保存する前にファイルを開き、ファイルオブジェクトを取得する段階で決定します。
pickleでファイルを保存するためにはその前段として、組み込み関数であるopen関数を使って保存するためのファイルを開きます。その時にテキストモードを使用するかバイナリモードを使用するかによって保存する形式が変わってきます。
なお、pickleによるテキストモードでの保存はPython2.7の場合簡単に行うことができますが、Python3.x系ではバイト型データの扱いを基本としているため、ご紹介するテキストモードでの保存手順ではエラーになります。
Python3.xを使用している場合はwbモードを使うことを強くおすすめします。
それでは実際にpickleでPythonオブジェクトをファイル化し保存してみましょう。
wモードでファイルを保存
wモードでpickleファイルを保存するコードは以下の通りです。
import pickle sample_list = [1,2,3] f = open('sample.textfile','w') pickle.dump(sample_list,f) f.close
まず、import文で標準ライブラリであるpickleをimportします。これによりPython環境でpickleを使用できるようになります。
次に保存するためのPythonオブジェクトを用意します。今回は1,2,3という連続する数字のリストを用意しました。このオブジェクトをpickleファイルに保存していきます。
ここまでの前準備ができたら、次は保存用のファイルを書き込みモードで開き、変数fにファイルオブジェクトを取得します。
書き込みモードの指定はopen(‘sample.textfile,’w’)の第2引数で行います。’w’と指定することでテキストモードの書き込みモードでファイルを開くことができます。
詳しくは下記のリンクで説明してます。
あとはpickle.dumpメソッドを使うだけで、ファイルに直列化したPythonオブジェクトを書き込むことができます。dumpメソッドの第一引数は直列化したいPythonオブジェクト、第2引数には保存先のファイルオブジェクトを指定します。
最後にファイルオブジェクトを閉じ、リストオブジェクトの保存が完了します。
wbモードでファイルを保存
次にバイナリモードでの保存を行ってみましょう。
テキストモードとの違いはopen関数の使用時の引数のみとなります。wモードでは第2引数を‘w’としていましたが、バイナリモードでは‘wb’と指定します。
import pickle sample_list = [1,2,3] f = open(‘sample.binaryfile’,’wb’) pickle.dump(sample_list,f) f.close
これでバイナリモードでの直列化(pickle化)が完了します。
別の環境でpickleファイルを復元する可能性がある場合は、特にテキストモードにする必要がなければ、バイナリモードでの使用をお勧めします。
pickleファイルを読み込み
では次に直列化したpickleファイルを読み込んでみましょう。この作業を非直列化(デシリアライズ)といいます。テキストデータもしくはバイナリデータとしてファイル保存したファイルを元のPythonオブジェクトに戻す作業です。
手順としては直列化の逆の作業となります。
pickleファイルを読み込みモードで開き、pickle.loadメソッドを使用しオブジェクトを復元します。
では実際にコードを見ていきましょう。
rモードでファイルを読み込み
では先ほどと同じように、まずはテキストモードでのファイルの読み込みを行っていきます。
import pickle f = open('sample.textfile','r') pickle.load(f)
こちらでは、pickleがimportされていない場合を考慮し再度pickleをインポートしています。
次に、保存されたpickleファイルを読み込みモードで開き、ファイルオブジェクトを取得します。
取得したファイルオブジェクトを引数としてpickle.loadメソッドを使用し、読み込んだファイルを非直列化
することにより、Pythonオブジェクトを復元することができます。
rbモードでファイルを読み込み
次にバイナリモードでの復元方法を説明します。こちらもopen関数の第二引数を‘r’から’rb’に変更するだけでバイナリモードでの復元を行うことができます。
import pickle f = open(‘sample.binaryfile’,’rb’) pickle.load(f)
バイナリモードで保存したpickleファイルはバイナリモードで復元する必要があるのでその点は注意してください。
pickleファイルが開けないときの対策
pickleファイルの復元操作をしていると、pickleファイルが開けないというトラブルに遭遇することがあります。その場合まず次の二つの原因を疑ってみてください。
・保存形式がバイナリモードなのに開き方がバイナリモードでない。もしくはその逆である。
・プロトコルバージョンが違う場合
先ほど、pickleファイルの保存と復元についてバイナリモードとテキストモードが存在することを説明しました。
各モードの保存と復元は対になるもので、テキストモードで保存したファイルをバイナリモードで復元することはできませんし、その逆もまたしかりです。保存と復元は同じモードで行う必要があります。
![Untitled Diagram](https://www.sejuku.net/blog/wp-content/uploads/2017/08/Untitled-Diagram.png)
次にプロトコルバージョンが違う場合にもpickleファイルが開けなくなります。
pickleのプロトコルバージョンとはpickleが行う処理のバージョンのことで、pickleでは複数のプロトコルバージョンを使用することができます。
注意点としては、プロトコルバージョン2で直列化したファイルは同じプロトコルバージョン2で非直列化する必要があるということです。
プロトコルバージョンは数字が大きくなるほどより高度なpickle 化をサポートしており、使用可能なバージョンはPythonのバージョンによっても違ってきます。
Python2.7では標準的なプロトコルとしてプロトコルバージョン0を使っています。一方、python3.xではプロトコルバージョン3をデフォルトのプロトコルとして使用しています。またpython3.4以降のバージョンの場合プロトコルを指定することによりプロトコルバージョン4を使用することもできます。
![protocol](https://www.sejuku.net/blog/wp-content/uploads/2017/08/protocol.png)
pickleでは、pickle.loadメソッドでpickleファイルを読み込む際に、プロトコルバージョンを自動で判別しそのプロトコルバージョンで復元を行う仕様になっています。
そのためPython2.7で保存したpickleファイル(プロトコルバージョン0)をPython3.x(プロトコルバージョン3)で読み込むときにプロトコルバージョンを気にする必要はありません。
しかし、Python3.6(プロトコルバージョン4)で保存したpickleファイルをPython2.7(プロトコルバージョン2)で読み込もうとすると、バージョンとして対応範囲外となるのでエラーとなります。
もし、Python2.7で読み込む可能性があるのであれば、プロトコルバージョン2を使ってpickleファイルを保存する必要があります。
では実際にプロトコルバージョンの指定方法についてコードで見ていきましょう。
import pickle sample_list = [1,2,3] f = open(‘sample.binaryfile’,”wb”) pickle.dump(sample_list,f,protocol=2) f.close
プロトコルバージョンの指定方法は難しくありません。
pickle.dumpメソッドにprotocol=バージョンという引数を追加するだけでそのバージョンで使用可能なプロトコルを指定することができます。
まとめ
いかがでしたか?
今回はPythonオブジェクト保存と復元にpickleを使用する方法について解説しました。
pickleを使う事で直列化(シリアライズ)、非直列化(デシリアライズ)を簡単に行えるのでぜひ活用してくださいね!
pickleや直列化についてイメージがわかないなと思ったらまたこの記事を参考にしてください。