mei_13のPython講座 ロゴ

【解説】Pythonのオブジェクトをそのまま保存?「pickle」モジュールの使い方と注意点




Pythonのオブジェクトをそのまま保存?「pickle」モジュールの使い方と注意点


Hirokiのアイコン
【Hiroki】 Yukiさん、こんにちは! 最近、Pythonで少し複雑なプログラムを作っているんですけど、一つ悩みがあるんです。 プログラムを終了させると、それまでに計算したデータや、せっかく作ったリストや辞書の中身が消えてしまいますよね? また次にプログラムを動かすときに、前の続きからデータを使いたい場合はどうすればいいんでしょうか。


Yukiのアイコン
【Yuki】 Hirokiくん、こんにちは...。 なるほど、データの「永続化(えいぞくか)」について悩んでいるんですね。 プログラムが終わってもデータを残しておきたいという願いは、開発をしていれば必ずと言っていいほど直面する問題だと思います...。


Hirokiのアイコン
【Hiroki】 永続化、ですか。 今はテキストファイルに書き出す方法を考えてみたんですが、リストの中に辞書が入っていたりすると、文字列に変換して保存して、読み込むときにまた元に戻すのがすごく大変そうで...。もっと簡単に、Pythonのデータをそのまま「ポイッ」と保存できる方法はありませんか?


Yukiのアイコン
【Yuki】 それなら、Pythonに標準で備わっている「pickle(ピックル)」というモジュールを使うのが、一番の近道かもしれません...。 pickleを使えば、Pythonのオブジェクトをほぼそのままの形でファイルに保存して、後でそっくりそのまま復元することができるんです。 今日は、このpickleの仕組みや使い方、そして使うときに絶対に気をつけてほしいことについて、一緒にお話ししていきましょうか...。

pickleとは何か?


Yukiのアイコン
【Yuki】 まず、pickleが何をしているのかを簡単に説明しますね...。 Pythonの世界にあるオブジェクト(リスト、辞書、あるいは自分で作ったクラスのインスタンスなど)を、ファイルに保存できるような「バイト列(バイナリ形式のデータ)」に変換することを、「シリアル化(シリアライズ)」と言います。 逆に、そのバイト列を読み込んで、元のPythonオブジェクトに戻すことを「逆シリアル化(デシリアライズ)」と呼びます。


Hirokiのアイコン
【Hiroki】 シリアル化...。なんだか難しそうな言葉ですね。


Yukiのアイコン
【Yuki】 ふふ、そうですね。でもイメージとしては、料理の「漬物(pickle)」を思い浮かべるとわかりやすいかもしれません...。 新鮮な野菜(データ)を、保存が効くように樽(ファイル)の中に漬け込んで、食べたいときにまた取り出す...。pickleという名前も、そこから来ていると言われているんですよ。 一度バイト列という「保存に適した形」にしてしまえば、ハードディスクに保存したり、ネットワーク越しに送ったりできるようになるんです。


Hirokiのアイコン
【Hiroki】 なるほど!だから「pickle」っていう名前なんですね。 テキスト形式のJSONとかとは違うんですか?


Yukiのアイコン
【Yuki】 いいところに気が付きましたね...。 JSONもシリアル化の一つですが、JSONは「テキスト(文字)」として保存します。 それに対して、pickleは「バイナリ(0と1の並び)」として保存するのが大きな違いです。 pickleはPython専用の形式なので、Pythonにしか存在しない特殊なデータ型もそのまま保存できるという強みがありますが、逆に言うとPython以外の言語(例えばJavaScriptやRubyなど)では読み込むのが難しいという側面もあります...。 でも、Python同士でやり取りするなら、これほど強力な味方はいないと思います。

基本的な使い方:オブジェクトの保存と読み込み


Hirokiのアイコン
【Hiroki】 実際にどうやって使うのか、コードを見てみたいです!


Yukiのアイコン
【Yuki】 はい。まずは、一番シンプルな方法から見ていきましょう...。 pickleモジュールを使うには、まず import pickle と書く必要があります。 データを保存するときは pickle.dump()、読み込むときは pickle.load() という関数を使います。


Hirokiのアイコン
【Hiroki】 ダンプ(dump)とロード(load)ですね。覚えやすいです。


Yukiのアイコン
【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のアイコン
【Hiroki】 おお、これだけでいいんですか? open() のモードが 'w' じゃなくて 'wb' になっているのがポイントですね。


Yukiのアイコン
【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のアイコン
【Hiroki】 すごいです! 辞書の形がそのまま復活していますね。 これなら、リストの中に辞書が入っていても、その逆でも、複雑な構造のまま保存できそうです。


Yukiのアイコン
【Yuki】 そうなんです。階層が深くても、pickleが自動的に解析して保存してくれるので、人間がパズルを解くようにデータを整理する必要はありません...。 開発者の手間を減らすために生まれた、とても優しいツールだと思います。 誰かの役に立ちたい、という想いが形になったような便利な機能ですよね。

実際に動かしてみましょう


Hirokiのアイコン
【Hiroki】 Yukiさん、他にも便利な使い方はありますか? いちいちファイルを作らずに、とりあえず変数の中にバイナリとして持っておきたい、みたいな時もあると思うんです。


Yukiのアイコン
【Yuki】 ありますよ...。ファイルに直接書き込むのではなく、メモリ上でバイナリデータ(bytesオブジェクト)に変換したいときは、dump ではなく dumpsload ではなく 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のアイコン
【Hiroki】 なるほど! dumps の方はファイルオブジェクトがいらないから、ちょっとした処理の間にデータをシリアル化して、どこかに送る準備をするときなんかに使えそうですね。


Yukiのアイコン
【Yuki】 ええ、その通りだと思います...。 ちなみに、pickleで保存できるのは基本的な型だけではありません。 自分で定義したクラスのインスタンスも保存できるんですよ。


Hirokiのアイコン
【Hiroki】 えっ、クラスのインスタンスもですか? それはすごく便利そうです!


Yukiのアイコン
【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のアイコン
【Hiroki】 これ、本当にすごいですね...。クラスの状態をそのまま保存できるなんて。 でも、読み込むときにもそのクラスが定義されていないとダメなんですよね?


Yukiのアイコン
【Yuki】 鋭いですね、Hirokiくん。その通りです...。 pickle.load() を実行するとき、プログラムの中にそのクラスの定義が見つからないと、「そんなクラスは知らないよ」というエラー(AttributeErrorなど)が出てしまいます。 あくまで「Pythonのプログラム」という共通のコンテキスト(文脈)の上で成り立つ魔法だと思ってくださいね...。

pickleを使う上での大きな注意点:セキュリティ


Yukiのアイコン
【Yuki】 さて...。ここまでpickleの便利なところを話してきましたが、ここからは一番大切な、そして少し怖い話をしなければなりません...。


Hirokiのアイコン
【Hiroki】 え、怖い話ですか...? 何か危険なことがあるんですか?


Yukiのアイコン
【Yuki】 はい。pickleを使う上で絶対に守らなければならないルールがあります。 それは、「信頼できない相手からもらったpickleファイルは、絶対に読み込んではいけない」ということです...。


Hirokiのアイコン
【Hiroki】 どうしてですか? ただのデータですよね?


Yukiのアイコン
【Yuki】 実は、pickleは単にデータを保存するだけではなく、「復元するときに特定の処理を実行させる」という仕組みを含めることができてしまうんです...。 もし、悪意のある人が作ったpickleファイルを pickle.load() してしまったら、その瞬間にあなたのコンピュータの中で勝手に怪しいプログラムが実行されたり、大事なファイルが消されたり、外部に情報を送信されたりする危険性があります。


Hirokiのアイコン
【Hiroki】 ええっ! データを読み込むだけで、ウイルスみたいな動きをさせることができちゃうんですか...。


Yukiのアイコン
【Yuki】 そうなんです...。これを「任意のコード実行」という脆弱性と呼びます。 Pythonの公式ドキュメントでも、この点については非常に強く警告されているんですよ。 だから、自分で作って保存したデータや、信頼できるサーバーから送られてきたことが確実なデータ以外には、決して使わないようにしてくださいね...。


Hirokiのアイコン
【Hiroki】 わかりました。インターネットの掲示板に落ちているような正体不明の .pkl ファイルを、安易に読み込んじゃダメってことですね。


Yukiのアイコン
【Yuki】 はい、約束ですよ...。 もし、どうしても不特定多数のユーザーとデータをやり取りしたい場合は、先ほど名前が出た JSON を使うのが安全です。 JSONはただのテキストデータなので、読み込むだけでプログラムが実行されるという心配はまずありませんから...。

他の形式(JSONなど)との使い分け


Hirokiのアイコン
【Hiroki】 そうすると、pickleとJSON、どうやって使い分ければいいんでしょうか。


Yukiのアイコン
【Yuki】 使い分けの基準を、いくつか挙げてみますね...。

  1. 安全性重視なら JSON 不特定多数が触れるデータや、外部との通信にはJSONを使いましょう。
  2. 他の言語と共有するなら JSON Webブラウザ(JavaScript)やスマホアプリと連携する場合は、世界標準のJSON一択です。
  3. Pythonだけで完結し、複雑なオブジェクトを楽に扱いたいなら pickle 自分で作った複雑なクラスのインスタンスや、多次元のリストなどを、手軽に一時保存したい場合はpickleが非常に便利です。
  4. 読みやすさ重視なら JSON JSONはテキストファイルなので、メモ帳で開いて中身を確認したり修正したりできます。pickleはバイナリなので、人間には読めません。


Hirokiのアイコン
【Hiroki】 なるほど。それぞれの長所を理解して選ぶのが大事なんですね。 僕は今、自分一人で使うツールを作っているので、まずはpickleを使ってデータの保存を試してみようと思います!


Yukiのアイコン
【Yuki】 それがいいと思います...。 あ、そうそう。pickleにも「プロトコル」というバージョンがあるんです。 Python 3.x系であればデフォルトで最適なものが選ばれるので、普段はあまり気にしなくて大丈夫ですが、すごく古いPython 2系とやり取りする場合は、バージョンを指定する必要があるかもしれません。 でも、Hirokiくんがこれから新しいコードを書くなら、あまり心配しなくても大丈夫なはずですよ...。

まとめ


Hirokiのアイコン
【Hiroki】 今日はありがとうございました、Yukiさん! pickleを使えば、今まであきらめていた「データの保存」がすごく身近になりそうです。


Yukiのアイコン
【Yuki】 どういたしまして...。最後に、今日お話しした内容を簡単におさらいしましょう。

  • pickleはPythonオブジェクトをバイナリ形式で保存(シリアル化)するためのモジュール。
  • pickle.dump(obj, file) でファイルに保存し、pickle.load(file) で復元する。
  • ファイルを開くときは必ずバイナリモード('wb''rb')を使う。
  • クラスのインスタンスなども丸ごと保存できる。
  • 【最重要】信頼できないpickleファイルは絶対に読み込まない(セキュリティリスクがあるため)。


Hirokiのアイコン
【Hiroki】 セキュリティのことは、肝に銘じておきます。 これで、僕のプログラムも一歩前進できそうです!


Yukiのアイコン
【Yuki】 よかったです...。 エラーが出たり、保存したはずのデータが上手く読み込めなかったりしたら、いつでも聞いてくださいね。 慣れるまでは少し「バイナリ」という概念が難しく感じるかもしれませんが、一度使えるようになると、Pythonがもっと自由で楽しくなると思いますよ...。 がんばってくださいね、Hirokiくん。


Hirokiのアイコン
【Hiroki】 はい、ありがとうございます!


参考資料: pickle --- Python オブジェクトの直列化 Pythonでのデータ永続化:pickleの使い方と注意点 (JSONとの比較に関する言及)



< PyCaret
コラム一覧に戻る
plotly >

この記事では基礎を解説しましたが、実務においては「もっと複雑なデータを扱いたい」「独自のシステムに組み込みたい」といった、個別の課題に直面することも多いはずです。

「自分で書く時間は最小限に抑え、プロの品質でツールを完成させたい」という方は、ぜひ一度ご相談ください。

「教わる」だけでなく「形にする」パートナーとして、フリーランスエンジニアのmei_13が最短ルートでの解決をサポートします。

➡ ココナラで制作・相談を依頼する(見積もり無料)


初心者から始められるPythonレッスン

プログラミング未経験者・初心者歓迎!
月額4,000円で質問し放題!!
● 完全オンライン
● 翌日までには必ず返信
● 挫折しない独自の学習メソッド
● 圧倒的高評価!!
テキストベースで時間を選ばない
● 高品質なサンプルコード
詳細はこちら
興味がある方はまず質問だけでもどうぞ!



AIアシスタント Yuki