Programmingバックエンド開発者

Pythonにおけるデータシリアル化の組み込みメカニズム(pickleおよびjsonモジュール)の動作を説明してください。これらはどのように異なり、何に使用され、無防備なシリアル化が秘める危険性は何ですか?

Hintsage AIアシスタントで面接を突破

回答

Pythonでは、オブジェクトをストレージ/転送のためにバイト列または文字列に変換する(シリアル化)ために、pickleおよびjsonモジュールが使用されます:

  • pickle は任意のPythonオブジェクト(クラスや関数さえも!)をシリアル化しますが、結果はバイナリのシーケンスになります。Pythonエコシステム内でのみ機能します。
  • json は単純なデータ構造(dict、list、str、int、float)のみをシリアル化し、結果は他の言語と互換性のある文字列(汎用フォーマット)になります。

Pickleを制御できない第三者間でデータを保存/転送するために使用するのは危険です。 なぜなら、デシリアル化時に任意の悪意のあるコードが実行される可能性があるからです。jsonはこの欠点を持っていません。

動作例:

import pickle import json # Pickle(バイナリシリアル化) data = {'x': 10, 'func': lambda x: x + 1} with open('data.pkl', 'wb') as f: pickle.dump(data, f) # JSON(単純なオブジェクトのみ) data = {'x': 10, 'y': [1, 2, 3]} with open('data.json', 'w') as f: json.dump(data, f)

トリッキーな質問

質問: 任意のPythonオブジェクトをセッション間でシリアル化および保存するためにpickleを使用できますか?このメカニズムはユーザーデータの保存に推奨されない理由は何ですか?

回答:

いいえ、pickleを至る所で使用するのは悪い習慣です。セキュリティ(「他人」のpickledオブジェクトをロードすると、実行が妥協される可能性がある)に加え、Pythonまたはクラスのバージョン不一致という問題があります。シリアル化されたオブジェクトは、クラスの構造が変更されるとロードできないか、正しく動作しない可能性があります。

例:

# pickleファイルの読み込み、クラスの構造が変更された場合 import pickle with open('old_version.pkl', 'rb') as f: obj = pickle.load(f) # AttributeErrorまたは構造の不一致

歴史

例 1

大規模なプロジェクトでユーザープロファイルの保存にpickleが使用されていました。Pythonのバージョンを更新し、クラスを変更した後、シリアル化されたオブジェクトの構造は互換性を失い、システムがクラッシュし、大部分のユーザーデータを失う結果となりました。


例 2

ウェブサービスでpickleがユーザーのセッションに使用されていました。悪意のある人物が悪意のあるpickledオブジェクトをロードし、サーバーへのコードインジェクションを実行することができました。


例 3

pickleを介して関数をシリアル化してネットワークを介して転送しようとする試みは、さまざまな環境で失敗しました:pickledラムダは異なる構成/バージョンのPythonを持つマシン間で移動できませんでした。