Q1信頼できない出所から受け取った pickle データをpickle.loadsする危険性として正しいのはどれですか?
pickle と base64 — オブジェクトとバイナリのテキスト化
pickle.dumps/loadsでdictや独自クラスをbytes化して完全復元し、base64.b64encode/b64decodeでバイナリをテキスト経路に乗せる方法を、戻り値の型を確認しながら学びます。
ファイルやネットワーク越しにデータを運ぶときに使う 2 つのモジュールを整理します。pickleはPython のオブジェクト(dict / クラスのインスタンス等)を後で完全に元の形へ戻せる状態で保存するライブラリ、base64は画像や音声などのデータを「英数字 + 記号 2 種だけの文字列」に変換して、メールや JSON にそのまま入れて運べる形にするライブラリです。どちらも内部処理や外部経路向けのデータ変換標準ライブラリです。
2 モジュールの用途を整理する
2 モジュールは入出力の組み合わせで用途が自然に分かれます。下の図で全体像を掴んでから、各セクションで典型用途と API を見ていきます。
pickle — Python オブジェクトをそのままバイト列に
pickleはPython オブジェクトを後で完全に復元できる形に変換する標準ライブラリです。変換結果はバイト列(bytes: 0〜255 の整数を並べた連続データで、文字列のような「文字の並び」ではなく「数値の並び」を扱う型)になります。バイト列はファイルへの保存 / ネットワーク越しの送信 / 別プロセスへの受け渡しなど、「人が読まずに機械が処理する」場面の基本フォーマットとして使われます。
json と違ってdict / list / 文字列・数値だけでなく、独自クラスのインスタンスや関数オブジェクトも保存できる点が pickle の強みで、機械学習モデルの保存や、Python プロセス間でのオブジェクト受け渡しなどに使われます。
他人が作った 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") のバイナリモードで |
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) |
=でパディングされる。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で対応します。
理解度チェック
まずは1問ずつ答えてみましょう。
Q2pickle.dumps(obj)の戻り値の型はどれですか?
Q3URL のクエリパラメータに base64 文字列を載せたい場合、最適な関数はどれですか?