Pythonのオブジェクトをそのまま保存?「pickle」モジュールの使い方と注意点
![]()
【Hiroki】
Yukiさん、こんにちは!
最近、Pythonで少し複雑なプログラムを作っているんですけど、一つ悩みがあるんです。
プログラムを終了させると、それまでに計算したデータや、せっかく作ったリストや辞書の中身が消えてしまいますよね?
また次にプログラムを動かすときに、前の続きからデータを使いたい場合はどうすればいいんでしょうか。
![]()
【Yuki】
Hirokiくん、こんにちは...。
なるほど、データの「永続化(えいぞくか)」について悩んでいるんですね。
プログラムが終わってもデータを残しておきたいという願いは、開発をしていれば必ずと言っていいほど直面する問題だと思います...。
![]()
【Hiroki】
永続化、ですか。
今はテキストファイルに書き出す方法を考えてみたんですが、リストの中に辞書が入っていたりすると、文字列に変換して保存して、読み込むときにまた元に戻すのがすごく大変そうで...。もっと簡単に、Pythonのデータをそのまま「ポイッ」と保存できる方法はありませんか?
![]()
【Yuki】
それなら、Pythonに標準で備わっている「pickle(ピックル)」というモジュールを使うのが、一番の近道かもしれません...。
pickleを使えば、Pythonのオブジェクトをほぼそのままの形でファイルに保存して、後でそっくりそのまま復元することができるんです。
今日は、このpickleの仕組みや使い方、そして使うときに絶対に気をつけてほしいことについて、一緒にお話ししていきましょうか...。
pickleとは何か?
![]()
【Yuki】
まず、pickleが何をしているのかを簡単に説明しますね...。
Pythonの世界にあるオブジェクト(リスト、辞書、あるいは自分で作ったクラスのインスタンスなど)を、ファイルに保存できるような「バイト列(バイナリ形式のデータ)」に変換することを、「シリアル化(シリアライズ)」と言います。
逆に、そのバイト列を読み込んで、元のPythonオブジェクトに戻すことを「逆シリアル化(デシリアライズ)」と呼びます。
![]()
【Hiroki】
シリアル化...。なんだか難しそうな言葉ですね。
![]()
【Yuki】
ふふ、そうですね。でもイメージとしては、料理の「漬物(pickle)」を思い浮かべるとわかりやすいかもしれません...。
新鮮な野菜(データ)を、保存が効くように樽(ファイル)の中に漬け込んで、食べたいときにまた取り出す...。pickleという名前も、そこから来ていると言われているんですよ。
一度バイト列という「保存に適した形」にしてしまえば、ハードディスクに保存したり、ネットワーク越しに送ったりできるようになるんです。
![]()
【Hiroki】
なるほど!だから「pickle」っていう名前なんですね。
テキスト形式のJSONとかとは違うんですか?
![]()
【Yuki】
いいところに気が付きましたね...。
JSONもシリアル化の一つですが、JSONは「テキスト(文字)」として保存します。
それに対して、pickleは「バイナリ(0と1の並び)」として保存するのが大きな違いです。
pickleはPython専用の形式なので、Pythonにしか存在しない特殊なデータ型もそのまま保存できるという強みがありますが、逆に言うとPython以外の言語(例えばJavaScriptやRubyなど)では読み込むのが難しいという側面もあります...。
でも、Python同士でやり取りするなら、これほど強力な味方はいないと思います。
基本的な使い方:オブジェクトの保存と読み込み
![]()
【Hiroki】
実際にどうやって使うのか、コードを見てみたいです!
![]()
【Yuki】
はい。まずは、一番シンプルな方法から見ていきましょう...。
pickleモジュールを使うには、まず import pickle と書く必要があります。
データを保存するときは pickle.dump()、読み込むときは pickle.load() という関数を使います。
![]()
【Hiroki】
ダンプ(dump)とロード(load)ですね。覚えやすいです。
![]()
【Yuki】
では、具体的なコードを書いてみますね...。
例えば、Hirokiくんが作った大事なゲームの設定データが辞書形式であるとしましょう。
import pickle
# 保存したいデータ(オブジェクト)
game_settings = {
"user_name": "Hiroki",
"level": 42,
"items": ["sword", "shield", "potion"],
"is_pro": True
}
# 1. データの保存(シリアル化)
# 'wb' は「バイナリ形式で書き込む(write binary)」という意味です
with open("settings.pkl", "wb") as f:
pickle.dump(game_settings, f)
print("データを保存しました。")
![]()
【Hiroki】
おお、これだけでいいんですか?
open() のモードが 'w' じゃなくて 'wb' になっているのがポイントですね。
![]()
【Yuki】
その通りです...。pickleはバイナリデータを扱うので、必ず 'b'(binary) を付けるのを忘れないでくださいね。
もしこれを忘れて 'w' だけで開こうとすると、エラーになってしまうかもしれません...。
次に、保存したデータを読み込む方法も見てみましょう。
import pickle
# 2. データの読み込み(逆シリアル化)
# 'rb' は「バイナリ形式で読み込む(read binary)」という意味です
with open("settings.pkl", "rb") as f:
loaded_settings = pickle.load(f)
print("読み込んだデータ:", loaded_settings)
print("ユーザー名:", loaded_settings["user_name"])
![]()
【Hiroki】
すごいです! 辞書の形がそのまま復活していますね。
これなら、リストの中に辞書が入っていても、その逆でも、複雑な構造のまま保存できそうです。
![]()
【Yuki】
そうなんです。階層が深くても、pickleが自動的に解析して保存してくれるので、人間がパズルを解くようにデータを整理する必要はありません...。
開発者の手間を減らすために生まれた、とても優しいツールだと思います。
誰かの役に立ちたい、という想いが形になったような便利な機能ですよね。
実際に動かしてみましょう
![]()
【Hiroki】
Yukiさん、他にも便利な使い方はありますか?
いちいちファイルを作らずに、とりあえず変数の中にバイナリとして持っておきたい、みたいな時もあると思うんです。
![]()
【Yuki】
ありますよ...。ファイルに直接書き込むのではなく、メモリ上でバイナリデータ(bytesオブジェクト)に変換したいときは、dump ではなく dumps、load ではなく loads を使います。
末尾の s は「String(文字列/バイト列)」の s だと考えると分かりやすいかもしれませんね。
import pickle
data = [1, 2, 3, {"key": "value"}]
# オブジェクトをバイト列に変換
binary_data = pickle.dumps(data)
print("バイナリデータ:", binary_data)
# バイト列からオブジェクトに復元
restored_data = pickle.loads(binary_data)
print("復元されたデータ:", restored_data)
![]()
【Hiroki】
なるほど! dumps の方はファイルオブジェクトがいらないから、ちょっとした処理の間にデータをシリアル化して、どこかに送る準備をするときなんかに使えそうですね。
![]()
【Yuki】
ええ、その通りだと思います...。
ちなみに、pickleで保存できるのは基本的な型だけではありません。
自分で定義したクラスのインスタンスも保存できるんですよ。
![]()
【Hiroki】
えっ、クラスのインスタンスもですか? それはすごく便利そうです!
![]()
【Yuki】
少しだけ例を見せておきますね...。
import pickle
class Player:
def __init__(self, name, hp):
self.name = name
self.hp = hp
def info(self):
return f"名前: {self.name}, HP: {self.hp}"
# インスタンスを作成
hero = Player("ヒロキ", 100)
# インスタンスをそのまま保存
with open("player.pkl", "wb") as f:
pickle.dump(hero, f)
# --- 別の場所や別の時間で読み込む ---
with open("player.pkl", "rb") as f:
loaded_hero = pickle.load(f)
print(loaded_hero.info()) # メソッドもそのまま使えます
![]()
【Hiroki】
これ、本当にすごいですね...。クラスの状態をそのまま保存できるなんて。
でも、読み込むときにもそのクラスが定義されていないとダメなんですよね?
![]()
【Yuki】
鋭いですね、Hirokiくん。その通りです...。
pickle.load() を実行するとき、プログラムの中にそのクラスの定義が見つからないと、「そんなクラスは知らないよ」というエラー(AttributeErrorなど)が出てしまいます。
あくまで「Pythonのプログラム」という共通のコンテキスト(文脈)の上で成り立つ魔法だと思ってくださいね...。
pickleを使う上での大きな注意点:セキュリティ
![]()
【Yuki】
さて...。ここまでpickleの便利なところを話してきましたが、ここからは一番大切な、そして少し怖い話をしなければなりません...。
![]()
【Hiroki】
え、怖い話ですか...? 何か危険なことがあるんですか?
![]()
【Yuki】
はい。pickleを使う上で絶対に守らなければならないルールがあります。
それは、「信頼できない相手からもらったpickleファイルは、絶対に読み込んではいけない」ということです...。
![]()
【Hiroki】
どうしてですか? ただのデータですよね?
![]()
【Yuki】
実は、pickleは単にデータを保存するだけではなく、「復元するときに特定の処理を実行させる」という仕組みを含めることができてしまうんです...。
もし、悪意のある人が作ったpickleファイルを pickle.load() してしまったら、その瞬間にあなたのコンピュータの中で勝手に怪しいプログラムが実行されたり、大事なファイルが消されたり、外部に情報を送信されたりする危険性があります。
![]()
【Hiroki】
ええっ! データを読み込むだけで、ウイルスみたいな動きをさせることができちゃうんですか...。
![]()
【Yuki】
そうなんです...。これを「任意のコード実行」という脆弱性と呼びます。
Pythonの公式ドキュメントでも、この点については非常に強く警告されているんですよ。
だから、自分で作って保存したデータや、信頼できるサーバーから送られてきたことが確実なデータ以外には、決して使わないようにしてくださいね...。
![]()
【Hiroki】
わかりました。インターネットの掲示板に落ちているような正体不明の .pkl ファイルを、安易に読み込んじゃダメってことですね。
![]()
【Yuki】
はい、約束ですよ...。
もし、どうしても不特定多数のユーザーとデータをやり取りしたい場合は、先ほど名前が出た JSON を使うのが安全です。
JSONはただのテキストデータなので、読み込むだけでプログラムが実行されるという心配はまずありませんから...。
他の形式(JSONなど)との使い分け
![]()
【Hiroki】
そうすると、pickleとJSON、どうやって使い分ければいいんでしょうか。
![]()
【Yuki】
使い分けの基準を、いくつか挙げてみますね...。
- 安全性重視なら JSON 不特定多数が触れるデータや、外部との通信にはJSONを使いましょう。
- 他の言語と共有するなら JSON Webブラウザ(JavaScript)やスマホアプリと連携する場合は、世界標準のJSON一択です。
- Pythonだけで完結し、複雑なオブジェクトを楽に扱いたいなら pickle 自分で作った複雑なクラスのインスタンスや、多次元のリストなどを、手軽に一時保存したい場合はpickleが非常に便利です。
- 読みやすさ重視なら JSON JSONはテキストファイルなので、メモ帳で開いて中身を確認したり修正したりできます。pickleはバイナリなので、人間には読めません。
![]()
【Hiroki】
なるほど。それぞれの長所を理解して選ぶのが大事なんですね。
僕は今、自分一人で使うツールを作っているので、まずはpickleを使ってデータの保存を試してみようと思います!
![]()
【Yuki】
それがいいと思います...。
あ、そうそう。pickleにも「プロトコル」というバージョンがあるんです。
Python 3.x系であればデフォルトで最適なものが選ばれるので、普段はあまり気にしなくて大丈夫ですが、すごく古いPython 2系とやり取りする場合は、バージョンを指定する必要があるかもしれません。
でも、Hirokiくんがこれから新しいコードを書くなら、あまり心配しなくても大丈夫なはずですよ...。
まとめ
![]()
【Hiroki】
今日はありがとうございました、Yukiさん!
pickleを使えば、今まであきらめていた「データの保存」がすごく身近になりそうです。
![]()
【Yuki】
どういたしまして...。最後に、今日お話しした内容を簡単におさらいしましょう。
- pickleはPythonオブジェクトをバイナリ形式で保存(シリアル化)するためのモジュール。
pickle.dump(obj, file)でファイルに保存し、pickle.load(file)で復元する。- ファイルを開くときは必ずバイナリモード(
'wb'や'rb')を使う。 - クラスのインスタンスなども丸ごと保存できる。
- 【最重要】信頼できないpickleファイルは絶対に読み込まない(セキュリティリスクがあるため)。
![]()
【Hiroki】
セキュリティのことは、肝に銘じておきます。
これで、僕のプログラムも一歩前進できそうです!
![]()
【Yuki】
よかったです...。
エラーが出たり、保存したはずのデータが上手く読み込めなかったりしたら、いつでも聞いてくださいね。
慣れるまでは少し「バイナリ」という概念が難しく感じるかもしれませんが、一度使えるようになると、Pythonがもっと自由で楽しくなると思いますよ...。
がんばってくださいね、Hirokiくん。
![]()
【Hiroki】
はい、ありがとうございます!
参考資料: pickle --- Python オブジェクトの直列化 Pythonでのデータ永続化:pickleの使い方と注意点 (JSONとの比較に関する言及)
この記事では基礎を解説しましたが、実務においては「もっと複雑なデータを扱いたい」「独自のシステムに組み込みたい」といった、個別の課題に直面することも多いはずです。
「自分で書く時間は最小限に抑え、プロの品質でツールを完成させたい」という方は、ぜひ一度ご相談ください。
- 専門家の知見に基づいた、保守性の高いコード設計
- AIの専門家による、Gemini API等の最新AIを組み合わせた高度な自動化
- ChatGPT等が生成したコードのデバッグ・最適化
「教わる」だけでなく「形にする」パートナーとして、フリーランスエンジニアのmei_13が最短ルートでの解決をサポートします。


