順番に読み進めながら学べます

pickle と base64 — オブジェクトとバイナリのテキスト化

pickle.dumps/loadsでdictや独自クラスをbytes化して完全復元し、base64.b64encode/b64decodeでバイナリをテキスト経路に乗せる方法を、戻り値の型を確認しながら学びます。

ファイルやネットワーク越しにデータを運ぶときに使う 2 つのモジュールを整理します。picklePython のオブジェクト(dict / クラスのインスタンス等)を後で完全に元の形へ戻せる状態で保存するライブラリ、base64画像や音声などのデータを「英数字 + 記号 2 種だけの文字列」に変換して、メールや JSON にそのまま入れて運べる形にするライブラリです。どちらも内部処理や外部経路向けのデータ変換標準ライブラリです。

2 モジュールの用途を整理する

2 モジュールは入出力の組み合わせで用途が自然に分かれます。下の図で全体像を掴んでから、各セクションで典型用途と API を見ていきます。

2 モジュールの役割分担
pickleオブジェクト ↔ bytes内部保存・プロセス間base64バイナリ ↔ ASCII経路変換 (JSON/メール)
pickleオブジェクト ↔ bytes(内部保存・プロセス間)、base64バイナリ ↔ ASCII テキスト(経路変換、JSON / メール / URL)。用途が競合しないので組み合わせて使うこともある。

pickle — Python オブジェクトをそのままバイト列に

picklePython オブジェクトを後で完全に復元できる形に変換する標準ライブラリです。変換結果はバイト列bytes: 0〜255 の整数を並べた連続データで、文字列のような「文字の並び」ではなく「数値の並び」を扱う型)になります。バイト列はファイルへの保存 / ネットワーク越しの送信 / 別プロセスへの受け渡しなど、「人が読まずに機械が処理する」場面の基本フォーマットとして使われます。

pickle の典型 4 用途
ML モデル保存model.pkl ファイルプロセス間転送multiprocessing計算結果キャッシュ重い処理をスキップタスクキューCelery が引数を運ぶ
機械学習モデルの保存 / プロセス間でのオブジェクト転送 / 計算結果のキャッシュ / タスクキュー。共通点は、Python の世界の中で完結する内部用途であること — 外部とのやり取りには json を使う。

json と違ってdict / list / 文字列・数値だけでなく、独自クラスのインスタンスや関数オブジェクトも保存できる点が pickle の強みで、機械学習モデルの保存や、Python プロセス間でのオブジェクト受け渡しなどに使われます。

pickle.dumps / loads の対称性
Python オブジェクト(dict / インスタンス等)pickle.dumpsbytes(バイナリ表現)bytes(バイナリ表現)pickle.loadsPython オブジェクト(dict / インスタンス等)書き出し読み込み
上段はdumps = Python オブジェクト → bytesへ書き出す方向。下段はloads = bytes → Python オブジェクトへ読み込む方向。json と違って独自クラスのインスタンスもそのまま保存・復元でき、戻り値はテキストではなくバイト列(ファイルに書くときはバイナリモード "wb" / "rb"で開く)。

他人が作った pickle を絶対に loads しない

pickle.loads任意の Python コードを実行できるため、信頼できない出所のバイト列を渡すと任意コード実行の脆弱性になります。自分が作って自分が読み戻す用途に限定し、ネットワーク越しや他人から受け取ったデータには絶対に使わないこと。外部とのやり取りにはjsonを選びます。

関数役割備考
pickle.dumps(obj)Python オブジェクト → bytes戻り値は bytes(str ではない)
pickle.loads(b)bytes → Python オブジェクト信頼できる出所のみ
pickle.dump(obj, file)ファイルに書き出しopen(..., "wb") のバイナリモードで
pickle.load(file)ファイルから読み込みopen(..., "rb") のバイナリモードで

点数表の辞書を pickle でバイト列に変換し、戻り値の型を確認します。pickle のバイト列は環境依存で長さが変わるので、ここではで正しさを検証します。

① pickle モジュールを読み込んでください

② 辞書{"name": "Alice", "scores": [80, 90, 75]}を変数dataに用意してください

dataを pickle でバイト列に変換して変数pickledに入れ、型: ◯◯の形で型名を表示してください(bytesのはずです)

(正しく実行できれば解説が表示されます)

Python エディタ

コードを実行してください

実践 1 で作ったpickledを Python オブジェクトに復元し、元のdataと完全に一致するかを確かめます。実践 1 で定義した変数datapickledがそのまま使えるので、復元処理だけ書きます。

pickledpickle.loadsで復元し、変数restoredに入れてください

⑤ 復元したオブジェクトのname復元した name: ◯◯の形で、復元した値が元(pickled)と完全に等しいかを元と等しい: True / Falseの形で表示してください

Python エディタ

コードを実行してください

base64 — バイナリをテキストで運ぶ

base64任意のバイナリデータを「英数字 + 記号 2 種」だけの文字列に変換するためのモジュールです。元の 3 バイトを 4 文字に変換するため、サイズは約 1.33 倍に増えますが、メールの添付ファイル / JSON や URL に画像を埋め込む / SQL に bytes を保存するなど、「テキストしか通らない経路でバイナリを運びたい」場面で広く使われます。

基本 API は次の 2 つです。

関数入力戻り値
base64.b64encode(バイト列)bytes(変換したい元データ)Base64 にエンコードされた bytes
base64.b64decode(Base64)bytes / str(Base64 表現)元のバイト列(bytes)
base64 の典型 4 用途
JSON / HTML に画像data:image/png;base64,…メール添付MIME の仕組みJWT トークン(Web 認証用)ペイロード表現環境変数に証明書改行を含むデータを 1 行に
JSON / HTML に画像を埋め込む(data URL) / メールの添付ファイル(MIME) / JWT トークンJSON Web Token: ログインユーザー情報を改ざん検出付きで運ぶ Web 認証トークン)のペイロード / 環境変数や設定ファイルに証明書を入れる。共通点は、テキストしか通らない経路でバイナリを運ぶこと。
base64 のしくみ
バイナリデータb"Python is fun!"b64encodeBase64 文字列UHl0aG9uIGlzIGZ1biE=Base64 文字列UHl0aG9uIGlzIGZ1biE=b64decodeバイナリデータb"Python is fun!"エンコードデコード
上段はencode = バイナリデータ → Base64 文字列へ変換する方向。下段はdecode = Base64 文字列 → 元のバイナリデータへ戻す方向。3 バイト6 ビットずつ 4 つに分割してA〜Z / a〜z / 0〜9 / + / /の 64 種類の文字に対応させる仕組みで、文字数は元の 4/3 倍になり、足りない部分は=でパディングされる。
import base64

# bytes → Base64
binary = b"Python is fun!"
encoded = base64.b64encode(binary)
print(encoded)              # b'UHl0aG9uIGlzIGZ1biE='
print(encoded.decode())     # UHl0aG9uIGlzIGZ1biE= (str に変換)

# Base64 → bytes
decoded = base64.b64decode(encoded)
print(decoded)              # b'Python is fun!'
print(decoded == binary)    # True

URL に埋めるなら urlsafe_b64

通常のb64encode+ と /を含むので、URL や JSON のキーに直接埋めるとエスケープが必要になります。URL や JSON で使うならbase64.urlsafe_b64encodeを選ぶと、+-/_に置き換えたURL セーフ版が得られます — 復元はbase64.urlsafe_b64decodeで対応します。

バイナリ文字列を Base64 でエンコードし、再度デコードして元と一致することを確かめます

① base64 モジュールを読み込んでください

② バイナリ文字列b"Python is fun!"を用意してください

③ Base64 にエンコードしたbytesbytes のまま表示するのではなく、ASCII 文字列に変換して Base64 文字列: ◯◯の形で表示してください

④ Base64 を元のバイナリに戻し、戻したバイナリが元と等しいかを元と等しい: True / Falseの形で表示してください

Python エディタ

コードを実行してください
QUIZ

理解度チェック

まずは1問ずつ答えてみましょう。

Q1信頼できない出所から受け取った pickle データをpickle.loadsする危険性として正しいのはどれですか?

Q2pickle.dumps(obj)の戻り値の型はどれですか?

Q3URL のクエリパラメータに base64 文字列を載せたい場合、最適な関数はどれですか?