Python Pickle モジュール
Python 開発では、実行時のオブジェクトを保存したり、プログラム再起動後に以前の状態を復元したりする必要がよくあります。例:
- 計算結果をディスクにキャッシュして、重複計算を避ける
- ユーザー設定やプログラムの中間状態を保存する
- 異なる Python プロセス間で複雑なオブジェクトを渡す
pickleモジュールはまさに、Python がこのような問題を解決するために提供しているものです公式の組み込みソリューション。
Python のpickleモジュールは、Python オブジェクトのシリアライズとデシリアライズを行うための標準ライブラリモジュールです。
Pickle を使い始める前に、2 つの中心的な概念を理解する必要があります:
- シリアライズ(Pickling):Python オブジェクトをバイト列に変換します
- デシリアライズ(Unpickling):バイト列を Python オブジェクトに戻します
pickleモジュールは、ほぼすべての Python オブジェクト(リスト、辞書、クラスインスタンスなど)をファイルに保存したり、ネットワーク経由で転送したりして、必要なときに再読み込みできます。
なぜ Pickle モジュールを使うのか?
- データの永続化:Python オブジェクトをファイルに保存して、プログラム終了後もこれらのデータにアクセスできるようにします。
- データ転送:ネットワーク経由で Python オブジェクトを転送します。例えば、分散システムでデータを渡す場合などです。
- 高速な保存と読み込み:
pickleモジュールは複雑なデータ構造を効率的に処理できるため、高速な保存と読み込みが必要なシーンに適しています。
Pickle の典型的な使用シーン
pickle以下のようなシーンに非常に適しています:
- ローカルデータの永続化
- プログラムの実行状態の保存と復元
- 中間計算結果のキャッシュ
- Python プロセス間通信(IPC)
- 機械学習モデルや特徴データの保存
適さないシーン:
- 言語をまたぐデータ交換
- フロントエンドとバックエンドのインターフェースでのデータ転送
- 信頼できないデータソースのデシリアライズ
Pickle はどのようなオブジェクトをサポートしていますか?
1. サポートされているオブジェクトの型
| 型 | サポートの有無 |
|---|---|
| int / float / bool / str | サポート |
| list / tuple / dict / set | サポート |
| None | サポート |
| カスタムクラスのインスタンス | サポート |
| ネスト構造 | サポート |
サポートされない、または推奨されないオブジェクト
- 開いているファイルオブジェクト
- socket、データベース接続
- オペレーティングシステムのリソース
- 実行環境の状態に依存するオブジェクト
モジュールのインポート
Pickle モジュールの使用は非常に簡単で、インポートするだけです:
import pickle
Pickle モジュールの基本的な使い方
1. オブジェクトのシリアライズ
使用するpickle.dump()メソッドで Python オブジェクトをシリアライズしてファイルに保存できます。
例
# Python オブジェクトを作成
data = {
'name': 'Alice',
'age': 25,
'hobbies': ['reading', 'traveling']
}
# オブジェクトをシリアライズしてファイルに保存
with open('data.pkl', 'wb') as file:
pickle.dump(data, file)
'wb'バイナリ書き込みモードでファイルを開くことを表します。pickle.dump()将dataオブジェクトをシリアライズしてファイルに書き込みます。
2. オブジェクトのデシリアライズ
使用するpickle.load()メソッドでファイルから Python オブジェクトを読み込んでデシリアライズできます。
例
# ファイルからオブジェクトを読み込んでデシリアライズ
with open('data.pkl', 'rb') as file:
loaded_data = pickle.load(file)
print(loaded_data)
'rb'バイナリ読み取りモードでファイルを開くことを表します。pickle.load()ファイルからバイトストリームを読み取り、Python オブジェクトにデシリアライズします。
3. バイト列へのシリアライズ
ファイルに保存したくない場合は、pickle.dumps() を使ってオブジェクトをバイト列にシリアライズできます:
例
data = [1, 2, 3, 4, 5]
# バイト列にシリアライズ
byte_data = pickle.dumps(data)
print(byte_data)
# 出力例: b'\x80\x04\x95\x0f\x00\x00\x00...'
4. バイト列からのデシリアライズ
pickle.loads() を使うと、バイト列からオブジェクトをデシリアライズできます:
例
byte_data = b'\x80\x04\x95\x0f\x00\x00\x00\x00\x00\x00\x00]\x94(K\x01K\x02K\x03K\x04K\x05e.'
# バイト列からデシリアライズ
original_data = pickle.loads(byte_data)
print(original_data)
# 出力: [1, 2, 3, 4, 5]
5. シリアライズ可能なオブジェクトの型
Pickle はほとんどの Python オブジェクトをシリアライズできます。以下を含みます:
- 基本データ型:整数、浮動小数点数、文字列、ブール値、None
- コレクション型:リスト、タプル、辞書、セット
- カスタムクラスのインスタンス
- 関数とクラス(一定の制限あり)
例
# 異なる型のデータをシリアライズ
numbers = [1, 2, 3]
text = "Hello, Pickle"
dictionary = {'key': 'value'}
tuple_data = (1, 2, 3)
set_data = {1, 2, 3}
# すべてのデータを1つのリストに入れる
all_data = [numbers, text, dictionary, tuple_data, set_data]
# シリアライズ
with open('mixed_data.pkl', 'wb') as f:
pickle.dump(all_data, f)
# デシリアライズ
with open('mixed_data.pkl', 'rb') as f:
loaded_data = pickle.load(f)
print(loaded_data)
6. カスタムクラスのシリアライズ
Pickle はカスタムクラスのインスタンスをうまく処理できます:
例
class Student:
def __init__(self, name, age, grade):
self.name = name
self.age = age
self.grade = grade
def __repr__(self):
return f"Student(name={self.name}, age={self.age}, grade={self.grade})"
# インスタンスを作成
student = Student("李四", 20, "大三")
# シリアライズ
with open('student.pkl', 'wb') as f:
pickle.dump(student, f)
# デシリアライズ
with open('student.pkl', 'rb') as f:
loaded_student = pickle.load(f)
print(loaded_student)
# 出力: Student(name=李四, age=20, grade=大三)
7. 複数オブジェクトのシリアライズ
pickle.dump() を複数回呼び出して、複数のオブジェクトを保存できます:
例
data1 = {'item': 'apple', 'count': 5}
data2 = ['banana', 'orange', 'grape']
data3 = 42
# 複数のオブジェクトを保存
with open('multiple.pkl', 'wb') as f:
pickle.dump(data1, f)
pickle.dump(data2, f)
pickle.dump(data3, f)
# 複数のオブジェクトを読み取る(順序は同じである必要があります)
with open('multiple.pkl', 'rb') as f:
loaded_data1 = pickle.load(f)
loaded_data2 = pickle.load(f)
loaded_data3 = pickle.load(f)
print(loaded_data1)
print(loaded_data2)
print(loaded_data3)
8. 実用的な応用例
例1:機械学習モデルの設定を保存・読み込み
例
# 機械学習モデルの設定をシミュレート
model_config = {
'model_type': 'RandomForest',
'n_estimators': 100,
'max_depth': 10,
'trained_date': '2024-01-13',
'accuracy': 0.95
}
# 設定を保存
with open('model_config.pkl', 'wb') as f:
pickle.dump(model_config, f)
# 設定を読み込み
with open('model_config.pkl', 'rb') as f:
config = pickle.load(f)
print(f"モデルタイプ: {config['model_type']}")
print(f"精度: {config['accuracy']}")
例2:計算結果のキャッシュ
例
import os
def expensive_computation(n):
"""時間のかかる計算をシミュレート"""
result = sum(i ** 2 for i in range(n))
return result
def compute_with_cache(n, cache_file='cache.pkl'):
# キャッシュが存在するか確認
if os.path.exists(cache_file):
with open(cache_file, 'rb') as f:
cache = pickle.load(f)
if n in cache:
print("キャッシュから結果を読み取ります")
return cache[n]
else:
cache = {}
# 計算を実行
print("計算を実行しています...")
result = expensive_computation(n)
# キャッシュに保存
cache[n] = result
with open(cache_file, 'wb') as f:
pickle.dump(cache, f)
return result
# 使用例
print(compute_with_cache(1000000)) # 1回目は計算される
print(compute_with_cache(1000000)) # 2回目はキャッシュから読み取られる
Pickle モジュールの注意点
- セキュリティ:
pickleモジュールはデシリアライズ時に任意のコードを実行するため、信頼できないソースからのpickleデータを読み込まないでください。悪意のある攻撃を避けるためです。 - 互換性:
pickle生成されるバイトストリームは Python 固有であり、Python のバージョンが異なると互換性の問題が発生する可能性があります。 - パフォーマンス:大規模なデータセットの場合、
pickleのシリアライズとデシリアライズは遅くなる可能性があります。より効率的なシリアライズツールの使用を検討できます。例えばjson或msgpack。
上級の使い方:カスタムオブジェクトのシリアライズ
pickleモジュールはカスタムクラスのシリアライズをサポートしています。デフォルトでは、pickleオブジェクトの属性とクラス名を保存します。より複雑なシリアライズロジックが必要な場合は、クラス内で実装できます__getstate__()と__setstate__()メソッド。
例
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __getstate__(self):
# カスタムシリアライズロジック
return {'name': self.name, 'age': self.age}
def __setstate__(self, state):
# カスタム逆シリアル化ロジック
self.name = state['name']
self.age = state['age']
# オブジェクトを作成してシリアル化
person = Person('Bob', 30)
with open('person.pkl', 'wb') as file:
pickle.dump(person, file)
# オブジェクトを逆シリアル化
with open('person.pkl', 'rb') as file:
loaded_person = pickle.load(file)
print(loaded_person.name, loaded_person.age)
pickle モジュールのよく使うメソッド
| メソッド | 説明 | 例 |
|---|---|---|
pickle.dump(obj, file) | オブジェクトをシリアル化してファイルに書き込む | pickle.dump(data, open('data.pkl', 'wb')) |
pickle.load(file) | ファイルから読み込んでオブジェクトを逆シリアル化する | data = pickle.load(open('data.pkl', 'rb')) |
pickle.dumps(obj) | オブジェクトをバイト列にシリアル化する | bytes_data = pickle.dumps([1, 2, 3]) |
pickle.loads(bytes) | バイト列からオブジェクトを逆シリアル化する | lst = pickle.loads(bytes_data) |
pickle.HIGHEST_PROTOCOL | 利用可能な最高のプロトコルバージョン(属性) | pickle.dump(..., protocol=pickle.HIGHEST_PROTOCOL) |
pickle.DEFAULT_PROTOCOL | デフォルトのプロトコルバージョン(属性、通常は4) | pickle.dumps(obj, protocol=pickle.DEFAULT_PROTOCOL) |
1. オブジェクトをファイルにシリアル化
例
data = {'name': 'Alice', 'age': 25}
with open('data.pkl', 'wb') as f:
pickle.dump(data, f, protocol=pickle.HIGHEST_PROTOCOL)
2. ファイルから逆シリアル化
例
loaded_data = pickle.load(f)
print(loaded_data) # 出力: {'name': 'Alice', 'age': 25}
3. バイト列へのシリアル化(ネットワーク転送/キャッシュ)
例
restored_list = pickle.loads(bytes_data)
pickle モジュールのプロトコルバージョン
| プロトコルバージョン | 説明 |
|---|---|
| 0 | 人間が読めるASCII形式(旧バージョン互換) |
| 1 | バイナリ形式(旧バージョン互換) |
| 2 | Python 2.3+ クラスオブジェクトの最適化サポート |
| 3 | Python 3.0+ デフォルトプロトコル(Python 2非対応) |
| 4 | Python 3.4+ より大きなオブジェクトとより多くのデータ型をサポート |
| 5 | Python 3.8+ メモリ最適化とデータ共有をサポート |