オブジェクトを保存可能な状態(バイトストリーム、テキスト表現など)に変換することをシリアライズと呼び、一方、前述の形式からオブジェクトにデータを変換することをデシリアライズと呼びます。シリアライズされた形式は、オブジェクトをメモリ上に再構築するために必要なすべての情報を、シリアライズされたときと同じ状態で保持します。
このガイドでは、Pickleモジュールを使ってPythonでデータをシリアライズおよびデシリアライズする方法を学びます。さらに、シリアライズ/デシリアライズされたデータを、Pandasを使って操作していきます。
注:Pythonプログラミング言語の全くの初心者の方は、ファイル操作についてある程度の知識があることをお勧めします。その場合は、Pythonでテキスト、JSON、CSVをファイルに保存するためのガイドをお読みください。
PythonのPicklingとUnpicklingとは何ですか?
Python には pickle
という組み込みパッケージがあり、それを使って pickling と unpickling の処理を行うことができます。
Pythonにおけるpicklingとunpicklingとは、Pythonの pickle
モジュールを使って、オブジェクトをバイトストリームに変換したり、逆にシリアライズやデシリアライズを記述するために使われる処理のことを指します。それでは、いくつかの例を見てみましょう
注意: pickle
モジュールは Python 3.x 以降の標準ライブラリで利用可能です。
辞書の内容を表示する次のようなコードを考えてみましょう。
import pickle
athletes = {
"Name": ["Cristiano Ronaldo", "Lionel Messi", "Eden Hazard", "Luis Suarez", "Neymar"],
"Club": ["Manchester United", "PSG", "Real Madrid", "Atletico Madrid", "PSG"]
}
print(athletes)
この場合、結果は
{
'Name': ['Cristiano Ronaldo', 'Lionel Messi', 'Eden Hazard', 'Luis Suarez', 'Neymar'],
'Club': ['Manchester United', 'PSG', 'Real Madrid', 'Atletico Madrid', 'PSG']
}
では、athletes
オブジェクトをバイナリファイルに “pickle” してみましょう。これは dump()
関数で行うことができます。この関数は 2 つのパラメータを受け取ります – ピクルス化するオブジェクトと、データを書き込む File
オブジェクトです。次のコードは、スクリプトが実行されているのと同じディレクトリに作成される新しいファイル athletes.txt
にデータを pickles します。
athletes_file = open('athletes.txt', 'wb')
pickle.dump(athletes, athletes_file)
athletes_file.close()
注意: ファイル操作で使用したモードは "wb"
で、これはバイナリファイルを書き込むのに使用されます。オブジェクトをバイトストリームに変換しているので、ファイルを扱うときは各モードで "b"
を使用することになります。
作成されたファイルの内容は、バイナリデータであり、人間が読める形式で保存されることを意図していないため、通常のテキストエディタで閲覧することはできません。この情報を読むには、このデータをアンピッキーまたはデシリアライズする必要があります。これは load()
関数で行うことができます!
load()` 関数は、ピクルス化されたファイルの内容を読み込み、データを読み込んで構築されたオブジェクトを返します。オブジェクトの種類や状態は、ファイルの内容に依存します。アスリート名の辞書を保存しているので、同じエントリーを持つこのオブジェクトが再構築されます。先ほど作成したpickleファイルをPythonオブジェクトに読み返して、その内容を表示してみましょう。
import pickle
athletes_file = open("athletes.txt", "rb")
athletes = pickle.load(athletes_file)
athletes_file.close()
print(athletes)
この結果、以下のようになります。
{'Name': ['Cristiano Ronaldo', 'Lionel Messi', 'Eden Hazard', 'Luis Suarez', 'Neymar'], 'Club': ['Manchester United', 'PSG', 'Real Madrid', 'Atletico Madrid', 'PSG']}
ご覧の通り、pickleされた全てのデータが戻ってきました。
注:バイナリデータの書き込みに "wb"
を使ったように、バイナリデータの読み出しにはファイルハンドリング時に "rb"
モードを使用しました。
さて、Pythonでpicklingとunpicklingのプロセスをカバーしたところで、Pandasの DataFrame
にその内容を格納するために、pickleされたファイルを読み込んでみましょう!
PandasのDataFrameでPickleファイルを読み込むには?
先ほどの例と同じデータを使用します。まず、Pandasのライブラリがインストールされていることを確認します。
$ pip install pandas
それでは、オブジェクトを Python DataFrame に変換するところから始めましょう。
import pickle
import pandas as pd
athletes = {
"Name": ["Cristiano Ronaldo", "Lionel Messi", "Eden Hazard", "Luis Suarez", "Neymar"],
"Club": ["Manchester United", "PSG", "Real Madrid", "Atletico Madrid", "PSG"]
}
df = pd.DataFrame(athletes)
print(df)
この結果は
Name Club
0 Cristiano Ronaldo Manchester United
1 Lionel Messi PSG
2 Eden Hazard Real Madrid
3 Luis Suarez Atletico Madrid
4 Neymar PSG
出力にあるように、インデックスを含む3列6行のPandas DataFrameオブジェクトを得ることができます。この後の処理は、DataFrameではない通常のオブジェクトを処理した場合と同様です。ファイルハンドリングと dump()
と load()
メソッドを用いて、まず Pandas の DataFrame
から pickle ファイルを作成し、次にバイトストリームを読み込んで Pandas の DataFrame
を取得することになります。
# ...
df = pd.DataFrame(athletes)
athelets_df_file = open("athletes_df.txt", "wb")
pickle.dump(df, athelets_df_file)
athelets_df_file.close()
上記のコードでは、PandasのDataFrameをバイトストリームとしてカレントディレクトリに athletes_df.txt
として格納するpickleファイルを作成します。
このDataFrameを再び使用したいときは、このファイルを解凍すれば元に戻すことができます。
import pickle
athletes_df_file = open("athletes_df.txt", "rb")
athletes = pickle.load(athletes_df_file)
athletes_df_file.close()
print(athletes)
この結果、以下のようになります。
Name Club
0 Cristiano Ronaldo Manchester United
1 Lionel Messi PSG
2 Eden Hazard Real Madrid
3 Luis Suarez Atletico Madrid
4 Neymar PSG
これがピクルスファイルのすごいところです。DataFrameオブジェクトに格納されている内容を読み込むだけでなく、
DataFrame` オブジェクトそのものを読み込むことができるのです。このような機能がなければ、プログラマはデータをJSONのようなアクセス可能な形式で保存し、そのJSONデータを新しいオブジェクトにロードして使用するのが一般的です。
picklingとunpicklingは、中間データ形式を使用したり、データをロードするためのメソッドを作成する手間を省いてくれます。
文字列へのピクルスと文字列からのアンピクルス
pickleモジュールが
dumps()と
loads()` メソッドも提供していることは知っておくとよいでしょう。これらのメソッドはPythonオブジェクトのpickleとunpickleを行いますが、データを格納するためにバイナリファイルを使用する代わりに、文字列データを返したり受け取ったりします。
それでは、 dumps()
と loads()
メソッドがPythonでどのように動作するかを理解するために、簡単な例を見てみましょう。
import pickle
simple_obj = {1: ['o', 'n', 'e'], "two": (1, 2), 3: "Three"}
pickled_obj = pickle.dumps(simple_obj)
print(pickled_obj)
この結果は
b'x80x04x95-x00x00x00x00x00x00x00}x94(Kx01]x94(x8cx01ox94x8cx01nx94x8cx01ex94ex8cx03twox94Kx01Kx02x86x94Kx03x8cx05Threex94u.'
出力を見てわかるように、dump()
メソッドで作成されたpickleファイルの代わりにバイナリ文字列が返されています。この文字列を受け取って、新しい変数にオブジェクトをロードすることができます。
out = pickle.loads(obj)
print(out)
この結果、以下のようになります。
{1: ['o', 'n', 'e'], 'two': (1, 2), 3: 'Three'}
この2つの方法は、Pythonベースのアプリケーション間の転送を容易にし、APIを通じてpickleされたデータを送信することができます。しかし、PythonベースのWebアプリケーションでは、代わりにJSONでシリアライズされたオブジェクトを使用するのが一般的でしょう。
結論
この記事では、後で使用するためにオブジェクトを保存するのに便利な Python の pickling と unpickling の操作について学びました。ロード()、ロード()
、ダンプ()、ダンプ()
といったメソッドは、組み込みの pickle
モジュールが提供する Python オブジェクトのバイトストリームへの変換と、バイトストリームからの変換を行うためのものです。
Pandas の DataFrame
オブジェクトへのデータの作成と読み込みは、Python の pickle
モジュールを使用して簡単に行うことができます。なお、このモジュールはクロスプログラミングの互換性を保証していないため、他のプログラミング言語でオブジェクトを使用する予定がある場合は、picklingやunpicklingは推奨されません。