"pickle" --- Python オブジェクトの直列化
****************************************

**ソースコード:** Lib/pickle.py

======================================================================

"pickle" モジュールは、Python オブジェクト構造を直列化・復元するための
バイナリプロトコルを実装しています。 *pickle 化 (pickling)* とは
Python オブジェクトの階層をバイトストリームに変換する処理です。 *非
pickle 化 (unpickling)* はその逆で、*バイナリファイル* や *bytes-like
object* からのバイトストリームをオブジェクトの階層に戻します。 pickle
化と非 pickle 化は、直列化 (serialization)、整列化 (marshalling) [1]、
平坦化 (flattening) とも呼ばれますが、ここでは混乱を避けるため「pickle
化」「非 pickle 化」という用語を使います。

警告:

  "pickle" モジュールは **安全ではありません** 。信頼できるデータのみ
  を非 pickle 化してください。**非 pickle 化の過程で任意のコードを実行
  する** ような、悪意ある pickle オブジェクトを生成することが可能です
  。信頼できない提供元からのデータや、改竄された可能性のあるデータの非
  pickle 化は絶対に行わないでください。データが改竄されていないことを
  保証したい場合は、 "hmac" による鍵付きハッシュ化を検討してください。
  信頼できないデータを処理する場合 "json" のようなより安全な直列化形式
  の方が適切でしょう。 json との比較 を参照してください。


他の Python モジュールとの関係
==============================


"marshal" との比較
------------------

Python には "marshal" という、より基本的な直列化モジュールもありますが
、一般に Python オブジェクトの直列化には常に "pickle" を優先して使って
ください。 "marshal" は主に Python の ".pyc" ファイルをサポートするた
めのものです。

"pickle" モジュールは、いくつかの重要な点で "marshal" と異なります:

* "marshal" はユーザー定義クラスやそのインスタンスを直列化できません。
  "pickle" はクラスのインスタンスを透過的に保存・復元できますが、クラ
  ス定義をインポートできる必要があり、オブジェクトを pickle 化したとき
  と同じモジュールに定義がなければなりません。

* "marshal" の直列化形式は、Python のバージョン間で移植できる保証があ
  りません。 主な用途が ".pyc" ファイルのサポートであるため、Python の
  実装者は必要に応じて、後方互換性のない形で直列化形式を変更することが
  あります。 一方、"pickle" の直列化形式は、互換性のある pickle プロト
  コルを選べば、Python のリリース間で後方互換性が保証されています。 た
  だし、言語に互換性のない変更が入った Python 2 と Python 3 の間でデー
  タをやり取りする場合は、pickle 化・非 pickle 化するコードで両者の型
  の違いに対処する必要があります。


"json" との比較
---------------

pickle プロトコルと JSON (JavaScript Object Notation) との基本的な違い
は以下のとおりです:

* JSON はテキストの直列化フォーマット (大抵の場合 "utf-8" にエンコード
  されますが、その出力は Unicode 文字列です) で、pickle はバイナリの直
  列化フォーマットです;

* JSON は人間が読める形式ですが、pickle はそうではありません;

* JSON は相互運用可能で Python 以外でも広く使用されていますが、pickle
  は Python 固有です;

* JSON は、デフォルトでは Python の組み込み型の一部しか表現することが
  できず、カスタムクラスに対しても行えません; pickle は極めて多くの
  Python の型を表現できます (その多くは賢い Python 内省機構によって自
  動的に行われます; 複雑なケースでは 固有のオブジェクト API によって対
  応できます)。

* pickleとは異なり、信頼できないJSONを復元するだけでは、任意のコードを
  実行できる脆弱性は発生しません。

参考: "json" モジュール: JSON への直列化および復元を行うための標準ライブラ
    リモジュール。


データストリームの形式
======================

"pickle" のデータ形式は Python 固有です。 そのため、ポインタの共有を表
現できない JSON など、外部の標準による制約を受けない利点があります。
一方、Python 以外のプログラムでは、pickle 化された Python オブジェクト
を再構成できない場合があります。

"pickle" のデータ形式は、デフォルトで比較的コンパクトなバイナリ表現を
使います。 サイズをさらに小さくする必要がある場合、pickle 化されたデー
タは効率よく 圧縮 できます。

"pickletools" モジュールには、"pickle" が生成したデータストリームを解
析するツールがあります。 "pickletools" のソースコードには、pickle プロ
トコルが使う命令コードについて詳しいコメントがあります。

現在 pickle 化には 6 種類のプロトコルを使用できます。より高いプロトコ
ルを使用するほど、作成された pickle を読み込むためにより高い Python の
バージョンが必要になります。

* プロトコルバージョン 0 はオリジナルの「人間に判読可能な」プロトコル
  で、Python の初期のバージョンとの後方互換性を持ちます。

* プロトコルバージョン 1 は旧形式のバイナリフォーマットで、これも
  Python の初期バージョンと互換性があります。

* プロトコルバージョン 2 は Python 2.3 で導入されました。このバージョ
  ンでは *新方式のクラス* のより効率的な pickle 化を提供しました。プロ
  トコル 2 による改良に関する情報は **PEP 307** を参照してください。

* プロトコルバージョン 3 は Python 3 で追加されました。 "bytes" オブジ
  ェクトを明示的にサポートしており、 Python 2.x で unpickle することは
  できません。これは Python 3.0から3.7のデフォルトプロトコルでした。

* プロトコルバージョン 4 は Python 3.4 で追加されました。このバージョ
  ンでは巨大なオブジェクトのサポート、より多くの種類のオブジェクトの
  pickle 化、および一部のデータ形式の最適化が行われました。これは
  Python 3.8から3.13 までのデフォルトプロトコルでした。プロトコル 4 に
  よる改良に関する情報は **PEP 3154** を参照してください。

* プロトコルバージョン 5 は Python 3.8 で追加されました。このバージョ
  ンでは帯域外データのサポートが追加され、また帯域内データに対するパフ
  ォーマンスが向上します。これはPython 3.14からのデフォルトプロトコル
  です。プロトコルバージョン 5 によってもたらされる改善についての情報
  は **PEP 574** を参照してください。

注釈:

  直列化は永続化よりも基本的な概念です。 "pickle" はファイルオブジェク
  トを読み書きしますが、永続化するオブジェクトの命名や、さらに複雑な同
  時アクセスの問題は扱いません。 "pickle" モジュールは、複雑なオブジェ
  クトをバイトストリームに変換し、そのバイトストリームを同じ内部構造の
  オブジェクトに戻せます。 バイトストリームの最も分かりやすい用途はフ
  ァイルへの書き込みですが、ネットワークで送信したり、データベースに保
  存したりすることも考えられます。 "shelve" モジュールは、DBM 形式のデ
  ータベースファイルでオブジェクトを pickle 化・非 pickle 化するための
  簡単なインターフェースを提供します。


モジュールインターフェース
==========================

オブジェクト階層を直列化するには、"dumps()" 関数を呼ぶだけです。同様に
、データストリームを復元するには、"loads()" 関数を呼びます。しかし、直
列化および復元に対してより多くのコントロールを行いたい場合、それぞれ
"Pickler" または "Unpickler" オブジェクトを作成することができます。

"pickle" モジュールは次の定数を提供します:

pickle.HIGHEST_PROTOCOL

   利用可能なうち最も高い プロトコルバージョン (整数)。この値は
   *protocol* 値として関数 "dump()"  および "dumps()" と、"Pickler" コ
   ンストラクターに渡すことができます。

pickle.DEFAULT_PROTOCOL

   pickle 化に使うデフォルトの プロトコルバージョン を表す整数です。
   "HIGHEST_PROTOCOL" より小さい場合があります。 現在のデフォルトはプ
   ロトコル 5 で、Python 3.8 で導入され、それより前のバージョンとは互
   換性がありません。 このバージョンでは帯域外バッファをサポートし、
   **PEP 3118** に準拠したデータをメインの pickle ストリームとは別に転
   送できます。

   バージョン 3.0 で変更: デフォルトプロトコルは 3 です。

   バージョン 3.8 で変更: デフォルトプロトコルは 4 です。

   バージョン 3.14 で変更: デフォルトプロトコルは 5 です。

"pickle" モジュールは、pickle 化をより便利に行うために次の関数を提供し
ます:

pickle.dump(obj, file, protocol=None, *, fix_imports=True, buffer_callback=None)

   オブジェクト *obj* を pickle 化し、すでにオープンしている *ファイル
   オブジェクト* *file* に書き込みます。"Pickler(file,
   protocol).dump(obj)" と等価です。

   引数 *file*, *protocol*, *fix_imports* および *buffer_callback* は
   "Pickler" のコンストラクタと同じ意味になります。

   バージョン 3.8 で変更: *buffer_callback* 引数が追加されました。

pickle.dumps(obj, protocol=None, *, fix_imports=True, buffer_callback=None)

   ファイルに書く代わりに、"bytes" オブジェクトとしてオブジェクト
   *obj* の pickle 表現を返します。

   引数 *protocol*, *fix_imports* および *buffer_callback* は
   "Pickler" のコンストラクタと同じ意味になります。

   バージョン 3.8 で変更: *buffer_callback* 引数が追加されました。

pickle.load(file, *, fix_imports=True, encoding='ASCII', errors='strict', buffers=None)

   あるオブジェクトの pickle 化表現を、オープンしている *ファイルオブ
   ジェクト* *file* から読み込み、その中で指定されているオブジェクト階
   層に再構成して返します。これは "Unpickler(file).load()" と等価です
   。

   pickle のプロトコルバージョンは自動的に検出されます。したがって
   protocol 引数は必要ありません。pickle 化オブジェクト表現より後のバ
   イト列は無視されます。

   引数 *file*, *fix_imports*, *encoding*, *errors*, *strict* および
   *buffers* は "Unpickler" のコンストラクタと同じ意味になります。

   バージョン 3.8 で変更: *buffers* 引数が追加されました。

pickle.loads(data, /, *, fix_imports=True, encoding='ASCII', errors='strict', buffers=None)

   オブジェクトのピックル化表現 *data* から再構成されたオブジェクト階
   層を返します。 *data* は バイトライクオブジェクト (*bytes-like
   object*) でなければなりません。

   pickle のプロトコルバージョンは自動的に検出されます。したがって
   protocol 引数は必要ありません。pickle 化オブジェクト表現より後のバ
   イト列は無視されます。

   引数 *fix_imports*, *encoding*, *errors*, *strict* および *buffers*
   は "Unpickler" のコンストラクタと同じ意味になります。

   バージョン 3.8 で変更: *buffers* 引数が追加されました。

"pickle" モジュールは 3 つの例外を定義しています:

exception pickle.PickleError

   他の pickle 化例外の共通基底クラス。"Exception" を継承しています。

exception pickle.PicklingError

   "Pickler" が pickle 化不可能なオブジェクトに遭遇したときに送出され
   るエラー。"PickleError" を継承しています。

   どんな種類のオブジェクトが pickle 化できるのか確認するには pickle
   化、非 pickle 化できるもの を参照してください。

exception pickle.UnpicklingError

   データ破損やセキュリティ違反のような、オブジェクトを非 pickle 化す
   るのに問題がある場合に送出されるエラー。"PickleError" を継承します
   。

   非 picke 化の最中に他の例外が送出されることもあるので注意してくださ
   い。これには AttributeError, EOFError, ImportError, IndexError が含
   まれます (ただし必ずしもこれらに限定されません)。

"pickle" モジュールは "Pickler"、"Unpickler"、"PickleBuffer" の 3 つの
クラスを公開しています:

class pickle.Pickler(file, protocol=None, *, fix_imports=True, buffer_callback=None)

   pickle 化されたオブジェクトのデータストリームを書き込むためのバイナ
   リファイルを引数にとります。

   任意の引数 *protocol* は、整数で、pickle 化で使用するプロトコルを指
   定します; サポートされているプロトコルは 0 から "HIGHEST_PROTOCOL"
   までになります。指定されない場合、"DEFAULT_PROTOCOL" が使用されます
   。負数が与えられた場合、"HIGHEST_PROTOCOL" が使用されます。

   引数 *file* は、単一の "bytes" 引数を受け付ける "write()" メソッド
   を持たなければなりません。 したがって、バイナリ書き込み用にオープン
   されたディスク上のファイル、"io.BytesIO" インスタンス、またはこのイ
   ンターフェースに適合するその他のカスタムオブジェクトを指定できます
   。

   *fix_imports* が真であり、かつ、*protocol* が 3 未満の場合、pickle
   は新しい Python 3 の名前と Python 2 で使用されていた古いモジュール
   名との対応付けを試みるので、pickle データストリームは Python 2 でも
   読み込み可能です。

   *buffer_callback* が "None" (デフォルト) の場合、バッファビューはス
   トリームの一部として*file* 中に直列化されます。

   *buffer_callback* が "None" でない場合、バッファビューを引数として
   何度でも呼び出されることがあります。 コールバックが "None" などの偽
   の値を返すと、渡されたバッファは 帯域外 で扱われます。 それ以外の場
   合は帯域内、つまり pickle ストリーム内に直列化されます。

   *buffer_callback* が "None" でなく、かつ *protocol* が "None" また
   は 5 より小さい場合はエラーとなります。

   バージョン 3.8 で変更: *buffer_callback* 引数が追加されました。

   dump(obj)

      *obj* の pickle 化表現を、コンストラクターで与えられた、すでにオ
      ープンしているファイルオブジェクトに書き込みます。

   persistent_id(obj)

      デフォルトでは何もしません。このメソッドはサブクラスがオーバーラ
      イドできるように存在します。

      "persistent_id()" が "None" を返す場合、通常通り *obj* が pickle
      化されます。それ以外の値を返した場合、"Pickler" がその値を *obj*
      のために永続的な ID として出力するようになります。この永続的な
      ID の意味は "Unpickler.persistent_load()" によって定義されていま
      す。"persistent_id()" によって返された値自身は永続的な ID を持つ
      ことができないことに注意してください。

      詳細および使用例については 外部オブジェクトの永続化 を参照してく
      ださい。

      バージョン 3.13 で変更: "Pickler" の C 実装に、このメソッドのデ
      フォルト実装を追加しました。

   dispatch_table

      pickler オブジェクトのディスパッチテーブルは、"copyreg.pickle()"
      で宣言できる種類の *リダクション関数* を登録するものです。 これ
      はクラスをキー、リダクション関数を値とするマッピングです。 リダ
      クション関数は、対応するクラスのインスタンスを 1 つ引数に取り、
      "__reduce__()" メソッドと同じインターフェースに従う必要がありま
      す。

      デフォルトでは、pickler オブジェクトは "dispatch_table" 属性を持
      たず、代わりに "copyreg" モジュールによって管理されるグローバル
      なディスパッチテーブルを使用します。しかし、特定の pickler オブ
      ジェクトによる pickle 化をカスタマイズするために
      "dispatch_table" 属性に dict-like オブジェクトを設定することがで
      きます。あるいは、"Pickler" のサブクラスが "dispatch_table" 属性
      を持てば、そのクラスのインスタンスに対するデフォルトのディスパッ
      チテーブルとして使用されます。

      使用例については ディスパッチテーブル を参照してください。

      Added in version 3.3.

   reducer_override(obj)

      "Pickler" のサブクラスで定義可能な特殊なリデューサ (reducer) で
      す。このメソッドは "dispatch_table" 内のいかなるリデューサよりも
      優先されます。このメソッドは "__reduce__()" メソッドのインターフ
      ェースと適合していなければなりません。また、メソッドが
      "NotImplemented" を返すことにより、 "dispatch_table" に登録され
      たリデューサにフォールバックして "obj" を直列化することもできま
      す。

      詳細な例については、 型、関数、その他のオブジェクトに対するリダ
      クションのカスタマイズ を参照してください。

      Added in version 3.8.

   fast

      廃止予定です。真値が設定されれば高速モードを有効にします。高速モ
      ードは、メモの使用を無効にします。それにより余分な PUT 命令コー
      ドを生成しなくなるので pickle 化処理が高速化します。自己参照オブ
      ジェクトに対しては使用すべきではありません。さもなければ
      "Pickler" に無限再帰を起こさせるでしょう。

      よりコンパクトな pickle 化を必要とする場合は、
      "pickletools.optimize()" を使用してください。

   clear_memo()

      pickler の「メモ」を消去します。

      メモは、共有されているオブジェクトや再帰的なオブジェクトを値では
      なく参照として pickle 化するために、pickler がすでに処理したオブ
      ジェクトを記憶するデータ構造です。 このメソッドは pickler を再利
      用するときに便利です。

class pickle.Unpickler(file, *, fix_imports=True, encoding='ASCII', errors='strict', buffers=None)

   これは pickle データストリームの読み込みのためにバイナリファイルを
   とります。

   pickle のプロトコルバージョンは自動的に検出されます。したがって
   protocol 引数は必要ありません。

   引数 *file* は "io.BufferedIOBase" のインターフェースと同様に、整数
   を引数にとる read() 、バッファを引数にとる readinto() 、引数を取ら
   ない readline() の3つのメソッドを持たなければなりません。したがって
   、 *file* はバイナリ読み込みモードでオープンされたディスク上のファ
   イル、 "io.BytesIO" オブジェクト、または上記インターフェース要件を
   満たす任意のカスタムオブジェクトのいずれかです。

   オプション引数 *fix_imports*, *encoding* および *errors* はPython 2
   で生成された pickle ストリームに対する互換性サポートを制御するため
   に使われます。 *fix_imports* が真の場合、 pickle は古い Python 2 の
   名前を Python 3 の新しい名前に対応づけようとします。 *encoding* と
   *errors* は pickle に Python 2 で  pickle 化された 8 ビット文字列を
   デコードする方法を指定します; これらの引数のデフォルト値はそれぞれ
   'ASCII' と 'strict' です。 *encoding* は 8 ビット文字列インスタンス
   をバイトオブジェクトとして読み込む場合は 'bytes' を指定します。
   Python 2 で pickle 化された NumPy 配列および "datetime", "date",
   "time" の各インスタンスを非 pickle 化するためには
   "encoding='latin1'" を使う必要があります。

   *buffers* が "None" (デフォルト値) の場合、非直列化に必要な全てのデ
   ータは pickle ストリームに含まれている必要があります。これは
   "Pickler" がインスタンス化されたとき (または "dump()" や "dumps()"
   が呼び出されたとき) に *buffer_callback* 引数に "None" を指定したこ
   とに相当します。

   *buffers* が "None" でない場合は、バッファを提供するオブジェクトの
   イテラブルでなければなりません。 pickle ストリームが 帯域外 (out-
   of-band) のバッファビューを参照するたびに、このイテラブルからバッフ
   ァを 1 つ取得します。 これらのバッファは、Pickler オブジェクトの
   *buffer_callback* に渡された順に並べます。

   バージョン 3.8 で変更: *buffers* 引数が追加されました。

   load()

      コンストラクターで与えられたオープンしたファイルオブジェクトから
      オブジェクトの pickle 化表現を読み込み、その中で指定されたオブジ
      ェクト階層に再構成して返します。オブジェクトの pickle 化表現より
      後のバイト列は無視されます。

   persistent_load(pid)

      デフォルトで "UnpicklingError" を送出します。

      もし定義されていれば、"persistent_load()" は永続的な ID *pid* に
      よって指定されたオブジェクトを返す必要があります。永続的な ID が
      無効な場合、"UnpicklingError" を送出しなければなりません。

      詳細および使用例については 外部オブジェクトの永続化 を参照してく
      ださい。

      バージョン 3.13 で変更: "Unpickler" の C 実装に、このメソッドの
      デフォルト実装を追加しました。

   find_class(module, name)

      必要なら *module* をインポートして、そこから *name* という名前の
      オブジェクトを返します。ここで *module* および *name* 引数は
      "str" オブジェクトです。その名前が示唆することに反して
      "find_class()" は関数を探すためにも使われることに注意してくださ
      い。

      サブクラスは、どんな型のオブジェクトを、どのようにロードするか (
      潜在的にはセキュリティリスクの減少) に関する制御を得るためにこれ
      をオーバーライドすることができます。詳細に関しては グローバル変
      数を制限する を参照してください。

      引数 "module", "name" を指定して 監査イベント
      "pickle.find_class" を送出します。

class pickle.PickleBuffer(buffer)

   pickle 化できるデータを表すバッファのラッパーです。 *buffer* は
   *bytes-like object* や N 次元配列のような、バッファを提供する オブ
   ジェクトでなければなりません。

   "PickleBuffer" はそれ自身バッファ機能を提供します。したがってこのク
   ラスのインスタンスを、バッファ機能を提供するオブジェクトを期待する
   "memoryview" など他の API に渡すことが可能です。

   "PickleBuffer" オブジェクトは pickle プロトコル 5 以降でのみ直列化
   できます。 帯域外の直列化 に対応しています。

   Added in version 3.8.

   raw()

      このバッファの背後にあるメモリ領域への "memoryview" を返します。
      戻り値のオブジェクトはフォーマット "B" (符号なしバイト) の C-連
      続な1次元のメモリビューです。バッファが C-連続でも Fortran-連続
      でもない場合 "BufferError" 例外が送出されます。

   release()

      PickleBuffer オブジェクトを通じてアクセスされる背後のバッファを
      解放します。


pickle 化、非 pickle 化できるもの
=================================

以下の型は pickle 化できます:

* 組み込み定数("None", "True", "False", "Ellipsis", と
  "NotImplemented")

* 整数、浮動小数点数、複素数

* 文字列、バイト列、バイト配列

* pickle 化可能なオブジェクトからなるタプル、リスト、集合および辞書

* モジュールのトップレベルからアクセスできる関数 (組み込み関数とユーザ
  ー定義関数。 "lambda" ではなく "def" で定義したもの)

* モジュールのトップレベルからアクセスできるクラス

* 上記のクラスのインスタンスのうち、"__getstate__()" を呼び出した結果
  が pickle 化可能なもの (詳しくは クラスインスタンスの pickle 化 を参
  照)。

pickle 化できないオブジェクトを pickle 化しようとすると、
"PicklingError" 例外が送出されます。この例外が起きたとき、すでに元のフ
ァイルには未知の長さのバイト列が書き込まれている場合があります。極端に
再帰的なデータ構造を pickle 化しようとした場合には再帰の深さ制限を越え
てしまうかもしれず、この場合には "RecursionError" が送出されます。この
制限は、"sys.setrecursionlimit()" で慎重に上げていくことは可能です。

関数 (組込みおよびユーザー定義) は、値ではなく、完全 *修飾名* で
pickle 化されます。[2]  これは、関数名のみがそれを含んでいるモジュール
およびクラスの名前をともなって pickle 化されることを意味します。関数の
コードやその属性は pickle 化されません。すなわち、非 pickle 化する環境
で定義したモジュールがインポート可能な状態になっており、そのモジュール
内に関数名のオブジェクトが含まれていなければなりません。この条件を満た
さなかった場合は例外が送出されます。[3]

クラスも同様に完全修飾名で pickle 化されるので、unpickle 化環境には同
じ制限が課せられます。クラス中のコードやデータは何も pickle 化されない
ので、以下の例ではクラス属性 "attr" が unpickle 化環境で復元されないこ
とに注意してください:

   class Foo:
       attr = 'A class attribute'

   picklestring = pickle.dumps(Foo)

pickle 化可能な関数やクラスがモジュールのトップレベルで定義されていな
ければならないのはこれらの制限のためです。

同様に、クラスのインスタンスが pickle 化された際、そのクラスのコードお
よびデータはオブジェクトと一緒に pickle 化されることはありません。イン
スタンスのデータのみが pickle 化されます。この仕様は、クラス内のバグを
修正したりメソッドを追加した後でも、そのクラスの以前のバージョンで作ら
れたオブジェクトを読み出せるように意図的に行われています。あるクラスの
多くのバージョンで使われるような長命なオブジェクトを作ろうと計画してい
るなら、そのクラスの "__setstate__()" メソッドによって適切な変換が行わ
れるようにオブジェクトのバージョン番号を入れておくとよいかもしれません
。


クラスインスタンスの pickle 化
==============================

この節では、クラスインスタンスがどのように pickle 化または非 pickle 化
されるのかを定義したり、カスタマイズしたり、コントロールしたりするのに
利用可能な一般的機構について説明します。

ほとんどの場合、インスタンスを pickle 化できるようにするために追加のコ
ードは必要ありません。デフォルトで、pickle はインスタンスのクラスと属
性を内省によって検索します。クラスインスタンスが非 pickle 化される場合
、通常その "__init__()" メソッドは実行 *されません* 。デフォルトの振る
舞いは、最初に初期化されていないインスタンスを作成して、次に保存された
属性を復元します。次のコードはこの振る舞いの実装を示しています:

   def save(obj):
       return (obj.__class__, obj.__dict__)

   def restore(cls, attributes):
       obj = cls.__new__(cls)
       obj.__dict__.update(attributes)
       return obj

クラスは、いくつかの特殊メソッドを提供することによって、デフォルトの振
る舞いを変更することができます:

object.__getnewargs_ex__()

   プロトコル 2 以降では、"__getnewargs_ex__()" メソッドを実装したクラ
   スは、非 pickle 化時に "__new__()" メソッドへ渡す値を指定できます。
   このメソッドは "(args, kwargs)" のペアを返さなければなりません。
   *args* はオブジェクトの構築に使う位置引数のタプル、*kwargs* は名前
   付き引数の辞書です。 これらは非 pickle 化時に "__new__()" メソッド
   へ渡されます。

   クラスの "__new__()" メソッドがキーワード専用引数を必要とする場合は
   、このメソッドを実装してください。 それ以外の場合は、互換性のために
   "__getnewargs__()" の実装を推奨します。

   バージョン 3.6 で変更: "__getnewargs_ex__()" がプロトコル 2 と 3 で
   も使われるようになりました。

object.__getnewargs__()

   このメソッドは "__getnewargs_ex__()" と同じような機能を提供しますが
   、位置引数のみをサポートします。このメソッドは引数のタプル "args"
   を返さなければならず、戻り値は非 pickle 化に際して "__new__()" メソ
   ッドに渡されます。

   "__getnewargs_ex__()" が定義されていると "__getnewargs__()" は呼び
   出しません。

   バージョン 3.6 で変更: Python 3.6 より前のプロトコル 2 と 3 では、
   "__getnewargs_ex__()" の代わりに "__getnewargs__()" が呼び出されて
   いました。

object.__getstate__()

   "__getstate__()" メソッドをオーバーライドすることで、クラスはインス
   タンスの pickle 化の動作をさらに変更できます。 このメソッドを呼び出
   して返されたオブジェクトが、デフォルトの状態の代わりにインスタンス
   の内容として pickle 化されます。 デフォルトの状態には次のケースがあ
   ります:

   * インスタンスの "__dict__" も "__slots__" もないクラスでは、デフォ
     ルトの状態は "None" です。

   * インスタンスの "__dict__" があり、"__slots__" がないクラスでは、
     デフォルトの状態は "self.__dict__" です。

   * インスタンスの "__dict__" と "__slots__" の両方があるクラスでは、
     デフォルトの状態は 2 つの辞書からなるタプルです。 1 つ目は
     "self.__dict__"、2 つ目はスロット名をスロットの値に対応付ける辞書
     です。 後者には値のあるスロットだけが含まれます。

   * "__slots__" があり、インスタンスの "__dict__" がないクラスでは、
     デフォルトの状態はタプルで、その最初の要素は "None"、2 番目の要素
     は前の項目で説明した、スロット名をスロットの値に対応付ける辞書で
     す。

   バージョン 3.11 で変更: "object" クラスに "__getstate__()" メソッド
   のデフォルト実装を追加しました。

object.__setstate__(state)

   非 pickle 化に際して、クラスが "__setstate__()" を定義している場合
   、それは非 pickle 化された状態とともに呼び出されます。その場合、状
   態オブジェクトが辞書でなければならないという要求はありません。そう
   でなければ、 pickle された状態は辞書で、その要素は新しいインスタン
   スの辞書に割り当てられます。

   注釈:

     pickle 化時に "__reduce__()" が返す状態の値が "None" の場合、非
     pickle 化時には "__setstate__()" メソッドを呼び出しません。

"__getstate__()" および "__setstate__()" メソッドの使い方に関する詳細
な情報については 状態を持つオブジェクトの扱い 節を参照してください。

注釈:

  非 pickle 化に際しては、 "__getattr__()", "__getattribute__()", また
  は "__setattr__()" といったメソッドがインスタンスに対して呼ばれるこ
  とがあります。これらのメソッドが何らかの内部的な不変条件が成り立つこ
  とに依存する場合、その型は "__new__()" メソッドを実装してそのような
  不変条件が成り立つようにすべきです。なぜならばインスタンスの非
  pickle 化においては "__init__()" メソッドは呼ばれないからです。

これらから見るように、pickle は上記のメソッドを直接使用しません。実際
には、これらのメソッドは "__reduce__()" 特殊メソッドを実装するコピープ
ロトコルの一部です。コピープロトコルは、pickle 化とオブジェクトのコピ
ーに必要な、データを取得するための統一されたインターフェースを提供しま
す。 [4]

強力ですが、クラスに "__reduce__()" メソッドを直接実装することはエラー
を起こしやすくなります。 この理由のため、クラスの設計者は可能なかぎり
高レベルインターフェース ("__getnewargs_ex__()"、"__getstate__()" およ
び "__setstate__()") を使用するべきです。 ただし、"__reduce__()" を使
う以外に方法がない場合、使うことで pickle 化が効率的になる場合、または
その両方に当てはまる場合についても説明します。

object.__reduce__()

   このインターフェースは現在、以下のように定義されています。
   "__reduce__()" メソッドは引数を取らず、文字列あるいは (こちらの方が
   好まれますが) タプルのいずれかを返すべきです (返されたオブジェクト
   は、しばしば "reduce value" と呼ばれます)。

   If a string is returned, the string should be interpreted as the
   name of a global variable.  It should be the object's local name
   relative to its module; the pickle module searches the module
   namespace to determine the object's module: for a given "obj" to be
   pickled, the "__module__" attribute is looked up on "obj" directly,
   which falls back to a lookup on the type of "obj" if no
   "__module__" instance attribute is set. This behaviour is typically
   useful for singletons.

   タプルが返された場合、それは 2〜6 要素長でなければなりません。オプ
   ションのアイテムは省略することができます。あるいはそれらの値として
   "None" を渡すことができます。各要素の意味は順に:

   * オブジェクトの初期バージョンを作成するために呼ばれる呼び出し可能
     オブジェクト。

   * 呼出し可能オブジェクトに対する引数のタプル。呼出し可能オブジェク
     トが引数を受け取らない場合、空のタプルが与えられなければなりませ
     ん。

   * 任意で、前述のオブジェクトの "__setstate__()" メソッドに渡される
     オブジェクトの状態。オブジェクトがそのようなメソッドを持たない場
     合、値は辞書でなければならず、それはオブジェクトの "__dict__" 属
     性に追加されます。

   * 任意で、連続した要素を yield する (シーケンスではなく) イテレータ
     ー。これらの要素は "obj.append(item)" を使用して、あるいはバッチ
     では "obj.extend(list_of_items)" を使用して、オブジェクトに追加さ
     れます。これは主としてリストのサブクラスに対して使用されますが、
     適切なシグネチャを持つ "append()" および "extend()" メソッドがあ
     るかぎり、他のクラスで使用することもできます。 ("append()" または
     "extend()" のどちらが使用されるかは、どの pickle プロトコルバージ
     ョンが使われるかに加えて追加されるアイテムの数にも依存します。し
     たがって、両方をサポートする必要があります)

   * 任意で、連続する key-value ペアを yield する (シーケンスでなく)
     イテレーター。これらの要素は "obj[key] = value" を使用して、オブ
     ジェクトに格納されます。これは主として辞書のサブクラスに対して使
     用されますが、"__setitem__()" を実装しているかぎり他のクラスで使
     用することもできます。

   * 任意で、シグネチャが "(obj, state)" である呼び出し可能オブジェク
     ト。このオブジェクトは、 "obj" のスタティックな "__setstate__()"
     メソッドの代わりに、ユーザーがオブジェクトの状態を更新する方法を
     プログラム的に制御することを許します。 "None" 以外の場合、この呼
     び出し可能オブジェクトは "obj" の "__setstate__()" メソッドに優先
     します。

     Added in version 3.8: 任意の6番目のタプル要素 "(obj, state)" が追
     加されました。

object.__reduce_ex__(protocol)

   別の方法として、"__reduce_ex__()" メソッドを定義することもできます
   。唯一の違いは、このメソッドは単一の整数引数、プロトコルバージョン
   を取る必要があるということです。もし定義された場合、pickle は
   "__reduce__()" メソッドよりもこのメソッドを優先します。さらに、
   "__reduce__()" は自動的に拡張版の同義語になります。このメソッドの主
   な用途は、古い Python リリースに対して後方互換性のある reduce value
   を提供することです。


外部オブジェクトの永続化
------------------------

オブジェクトの永続化を支援するため、"pickle" モジュールは pickle デー
タストリームの外にあるオブジェクトへの参照をサポートしています。 こう
したオブジェクトは永続的 ID で参照します。 永続的 ID は、プロトコル 0
では英数字の文字列 [5]、それより新しいプロトコルでは任意のオブジェクト
でなければなりません。

このような永続的 ID の解決方法は "pickle" モジュールでは定義していませ
ん。 解決処理は pickler と unpickler のユーザー定義メソッド、それぞれ
"persistent_id()" と "persistent_load()" に委譲します。

外部の永続的 ID を持つオブジェクトを pickle 化するには、pickler は、オ
ブジェクトを引数として取り、"None" またはそのオブジェクトの永続的 ID
を返す、カスタムの "persistent_id()" メソッドを持たなければなりません
。 "None" が返された場合、pickler はそのオブジェクトを通常どおり
pickle 化します。 永続的 ID の文字列が返された場合、pickler は、
unpickler がそれを永続的 ID として認識できるように、マーカーとともにそ
の ID を pickle 化します。

外部オブジェクトを非 pickle 化するには、unpickler は永続的 ID オブジェ
クトを取り被参照オブジェクトを返すカスタム "persistent_load()" メソッ
ドを持たなくてはなりません。

これは、外部のオブジェクトを参照によって pickle 化するために永続的 ID
をどのように使用するかを示す包括的な例です。

   # 永続的 ID を使い、外部のオブジェクトを参照として pickle 化する簡単な例。

   import pickle
   import sqlite3
   from collections import namedtuple

   # データベース内のレコードを表す簡単なクラス。
   MemoRecord = namedtuple("MemoRecord", "key, task")

   class DBPickler(pickle.Pickler):

       def persistent_id(self, obj):
           # MemoRecord を通常のクラスインスタンスとして pickle 化する代わりに、
           # 永続的 ID を出力する。
           if isinstance(obj, MemoRecord):
               # ここでの永続的 ID は、タグとデータベース内の特定のレコードを指すキーを
               # 含むタプルにすぎない。
               return ("MemoRecord", obj.key)
           else:
               # obj に永続的 ID がなければ None を返す。
               # これは obj を通常どおり pickle 化する必要があることを示す。
               return None


   class DBUnpickler(pickle.Unpickler):

       def __init__(self, file, connection):
           super().__init__(file)
           self.connection = connection

       def persistent_load(self, pid):
           # このメソッドは永続的 ID が現れるたびに呼ばれる。
           # ここで pid は DBPickler が返したタプル。
           cursor = self.connection.cursor()
           type_tag, key_id = pid
           if type_tag == "MemoRecord":
               # 参照されたレコードをデータベースから取得して返す。
               cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),))
               key, task = cursor.fetchone()
               return MemoRecord(key, task)
           else:
               # 正しいオブジェクトを返せない場合は必ずエラーを送出する。
               # そうしないと、unpickler は永続的 ID が参照するオブジェクトが
               # None だとみなしてしまう。
               raise pickle.UnpicklingError("unsupported persistent object")


   def main():
       import io
       import pprint

       # データベースを初期化し、データを挿入する。
       conn = sqlite3.connect(":memory:")
       cursor = conn.cursor()
       cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)")
       tasks = (
           'give food to fish',
           'prepare group meeting',
           'fight with a zebra',
           )
       for task in tasks:
           cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,))

       # pickle 化するレコードを取得する。
       cursor.execute("SELECT * FROM memos")
       memos = [MemoRecord(key, task) for key, task in cursor]
       # 独自の DBPickler を使ってレコードを保存する。
       file = io.BytesIO()
       DBPickler(file).dump(memos)

       print("Pickled records:")
       pprint.pprint(memos)

       # 試しにレコードを更新する。
       cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1")

       # pickle データストリームからレコードを読み込む。
       file.seek(0)
       memos = DBUnpickler(file, conn).load()

       print("Unpickled records:")
       pprint.pprint(memos)


   if __name__ == '__main__':
       main()


ディスパッチテーブル
--------------------

pickle 化に依存する他のコードの邪魔をせずに、一部のクラスの pickle 化
だけをカスタマイズしたい場合、プライベートのディスパッチテーブルを持つ
pickler を作成することができます。

"copyreg" モジュールによって管理されるグローバルなディスパッチテーブル
は "copyreg.dispatch_table" として利用可能です。したがって、
"copyreg.dispatch_table" の修正済のコピーをプライベートのディスパッチ
テーブルとして使用することを選択できます。

例えば

   f = io.BytesIO()
   p = pickle.Pickler(f)
   p.dispatch_table = copyreg.dispatch_table.copy()
   p.dispatch_table[SomeClass] = reduce_SomeClass

これは "SomeClass" クラスを特別に扱うプライベートのディスパッチテーブ
ルを持つ "pickle.Pickler" のインスタンスを作成します。あるいは、次のコ
ード

   class MyPickler(pickle.Pickler):
       dispatch_table = copyreg.dispatch_table.copy()
       dispatch_table[SomeClass] = reduce_SomeClass
   f = io.BytesIO()
   p = MyPickler(f)

これは同じことを行いますが、"MyPickler" のすべてのインスタンスがデフォ
ルトでプライベートのディスパッチテーブルを共有します。 一方、次のコー
ドを見てください。

   copyreg.pickle(SomeClass, reduce_SomeClass)
   f = io.BytesIO()
   p = pickle.Pickler(f)

"copyreg" モジュールのすべての利用者が共有するグローバルなディスパッチ
テーブルを変更します。


状態を持つオブジェクトの扱い
----------------------------

クラスの pickle 化の動作を変更する例を示します。 以下の "TextReader"
クラスはテキストファイルを開き、"readline()" メソッドが呼ばれるたびに
行番号と行の内容を返します。 "TextReader" インスタンスを pickle 化する
と、ファイルオブジェクトのメンバーを *除く* すべての属性を保存します。
非 pickle 化するとファイルを開き直し、最後の位置から読み取りを再開しま
す。 この動作は "__setstate__()" と "__getstate__()" メソッドで実装し
ています。

   class TextReader:
       """テキストファイルの行に番号を付けて表示する。"""

       def __init__(self, filename):
           self.filename = filename
           self.file = open(filename)
           self.lineno = 0

       def readline(self):
           self.lineno += 1
           line = self.file.readline()
           if not line:
               return None
           if line.endswith('\n'):
               line = line[:-1]
           return "%i: %s" % (self.lineno, line)

       def __getstate__(self):
           # すべてのインスタンス属性を含む self.__dict__ からオブジェクトの状態をコピーする。
           # 元の状態を変更しないよう、必ず dict.copy() メソッドを使う。
           state = self.__dict__.copy()
           # pickle 化できない要素を取り除く。
           del state['file']
           return state

       def __setstate__(self, state):
           # インスタンス属性 (filename と lineno) を復元する。
           self.__dict__.update(state)
           # 以前開いていたファイルの状態を復元する。
           # そのためにファイルを開き直し、行数が元に戻るまで読み進める。
           file = open(self.filename)
           for _ in range(self.lineno):
               file.readline()
           # 最後にファイルを保存する。
           self.file = file

使用例は以下のようになるでしょう:

   >>> reader = TextReader("hello.txt")
   >>> reader.readline()
   '1: Hello world!'
   >>> reader.readline()
   '2: I am line number two.'
   >>> new_reader = pickle.loads(pickle.dumps(reader))
   >>> new_reader.readline()
   '3: Goodbye!'


型、関数、その他のオブジェクトに対するリダクションのカスタマイズ
================================================================

Added in version 3.8.

"dispatch_table" は、ときにその柔軟性が十分でないことあります。 特に、
オブジェクトの型以外の別の条件で pickle 化をカスタマイズしたい場合や、
関数やクラスの pickle 化をカスタマイズしたい場合などです。

そのような場合、 "Pickler" クラスから派生したサブクラスで
"reducer_override()" メソッドを実装することができます。このメソッドは
任意のリダクション用タプルを返すことができます  ("__reduce__()" を参照
してください)。もしくは、従来の振る舞いにフォールバックするために
"NotImplemented" を返すこともできます。

"dispatch_table" と "reducer_override()" の両方が定義されている場合、
"reducer_override()" メソッドが優先されます。

注釈:

  パフォーマンス上の理由により、次に挙げるオブジェクトに対しては
  "reducer_override()" が呼ばれないことがあります: "None", "True",
  "False", および "int", "float", "bytes", "str", "dict", "set",
  "frozenset", "list", "tuple" の厳密なインスタンス。

以下は特定のクラスを pickle 化して再構成する単純な例です:

   import io
   import pickle

   class MyClass:
       my_attribute = 1

   class MyPickler(pickle.Pickler):
       def reducer_override(self, obj):
           """MyClass 用の独自のリデューサ。"""
           if getattr(obj, "__name__", None) == "MyClass":
               return type, (obj.__name__, obj.__bases__,
                             {'my_attribute': obj.my_attribute})
           else:
               # 他のオブジェクトでは通常のリダクションにフォールバックする
               return NotImplemented

   f = io.BytesIO()
   p = MyPickler(f)
   p.dump(MyClass)

   del MyClass

   unpickled_class = pickle.loads(f.getvalue())

   assert isinstance(unpickled_class, type)
   assert unpickled_class.__name__ == "MyClass"
   assert unpickled_class.my_attribute == 1


帯域外バッファ
==============

Added in version 3.8.

"pickle" モジュールは大量のデータの転送に使われることがあります。 その
ため、性能とリソース消費量を良好に保つには、メモリコピーの回数を最小限
に抑えることが重要になる場合があります。 しかし、"pickle" モジュールの
通常の動作では、グラフ状のオブジェクト構造を一連のバイトストリームに変
換するため、pickle ストリームへのデータのコピーと、ストリームからのデ
ータのコピーが本質的に伴います。

この制約は、*provider* (転送するオブジェクトの型の実装) と *consumer*
(通信システムの実装) の両方が、pickle プロトコル 5 以降の帯域外転送機
能をサポートしていれば回避できます。


生産者 API
----------

pickle 化される大きなサイズのデータオブジェクトは、プロトコル 5 以上に
対応した "__reduce_ex__()" メソッドを実装しなければなりません。 このメ
ソッドは大きなデータに対して ("bytes" オブジェクトなどの代わりに)
"PickleBuffer" インスタンスを返します。

"PickleBuffer" オブジェクトは、その背後にあるバッファが帯域外データ転
送に対応していることを *示します*。 このオブジェクトは "pickle" モジュ
ールの通常の使い方とも互換性があります。 ただし、消費者はバッファを自
分で処理することを "pickle" に明示的に伝えることもできます。


消費者 API
----------

通信システムは、オブジェクトグラフを直列化するときに生成された
"PickleBuffer" オブジェクトのカスタマイズされた処理を有効化することが
できます。

送信側は *buffer_callback* 引数を "Pickler" (または "dump()" や
"dumps()" 関数) に渡す必要があります。この関数はオブジェクトグラフを
pickle 化するときに生成されるそれぞれの "PickleBuffer" を引数として呼
ばれます。 *buffer_callback* によって蓄積されたバッファは、それが保持
するデータのコピーを pickle ストリームに送らず、軽量なマーカーが挿入さ
れるだけです。

受信側は *buffers* 引数を "Unpickler" (または "load()" や "loads()" 関
数) に渡す必要があります。これは *buffer_callback* に渡されたバッファ
のイテラブルです。このイテラブルは  *buffer_callback* に渡されたのと同
じ順番でバッファを返さなければなりません。これらのバッファは、pickle
化処理によって "PickleBuffer" オブジェクトを生成したオブジェクトの再構
築処理で期待されるデータを提供します。

送信側と受信側の間では、通信システムは帯域外バッファを転送する独自の仕
組みを自由に実装できます。 考えられる最適化には、共有メモリの利用やデ
ータ型に応じた圧縮があります。


使用例
------

以下は、帯域外バッファを使った pickle 化に対応する "bytearray" のサブ
クラスを実装する簡単な例です。

   class ZeroCopyByteArray(bytearray):

       def __reduce_ex__(self, protocol):
           if protocol >= 5:
               return type(self)._reconstruct, (PickleBuffer(self),), None
           else:
               # pickle プロトコル 4 以下では PickleBuffer を使えない。
               return type(self)._reconstruct, (bytearray(self),)

       @classmethod
       def _reconstruct(cls, obj):
           with memoryview(obj) as m:
               # 元のバッファオブジェクトへの参照を取得する
               obj = m.obj
               if type(obj) is cls:
                   # 元のバッファオブジェクトが ZeroCopyByteArray なので、そのまま返す。
                   return obj
               else:
                   return cls(obj)

再構成関数 ("_reconstruct" クラスメソッド) は、受け取ったバッファが持
っているオブジェクトを、それが正しい型であれば、そのまま返します。これ
は、このおもちゃのような例において、ゼロコピーの挙動を模擬的に行う簡単
な方法です。

消費者側では、これらのオブジェクトを通常の方法で pickle 化することがで
きます。この場合非直列化処理は元のオブジェクトのコピーを返します:

   b = ZeroCopyByteArray(b"abc")
   data = pickle.dumps(b, protocol=5)
   new_b = pickle.loads(data)
   print(b == new_b)  # True
   print(b is new_b)  # False: コピーが作られた

いっぽう直列化において *buffer_callback* を設定し、非直列化において蓄
積されたバッファを渡した場合、コピーではなく元のオブジェクトを得ること
ができます:

   b = ZeroCopyByteArray(b"abc")
   buffers = []
   data = pickle.dumps(b, protocol=5, buffer_callback=buffers.append)
   new_b = pickle.loads(data, buffers=buffers)
   print(b == new_b)  # True
   print(b is new_b)  # True: コピーは作られなかった

この例では "bytearray" がそれ自身メモリを割り当てるという性質による制
限があります: すなわち、他のオブジェクトのメモリを参照する "bytearray"
を生成することはできません。しかし、 NumPy 配列のようなサードパーティ
のデータ型ではそのような制限はなく、異なるプロセス間または異なるシステ
ム間で、ゼロコピー (または最小限のコピー) でのpickle 処理の利用が可能
です。

参考: **PEP 574** -- Pickle プロトコルバージョン 5 による帯域外データ


グローバル変数を制限する
========================

デフォルトで、非 pickle 化は pickle データ内で見つけたあらゆるクラスや
関数をインポートします。多くのアプリケーションでは、この振る舞いは受け
入れられません。なぜなら、それによって unpickler が任意のコードをイン
ポートして実行することが可能になるからです。この手の巧妙に作られた
pickle データストリームがロードされたときに何を行うかをちょっと考えて
みてください:

   >>> import pickle
   >>> pickle.loads(b"cos\nsystem\n(S'echo hello world'\ntR.")
   hello world
   0

この例において、unpickler は "os.system()" 関数をインポートして、次に
文字列の引数 "echo hello world" を適用しています。この例は無害ですが、
システムを破壊する例を想像するのは難しくありません。

この理由のため、"Unpickler.find_class()" をカスタマイズすることで非
pickle 化で何を得るかを制御したくなるかもしれません。その名前が示唆す
るのと異なり、"Unpickler.find_class()" はグローバル (クラスや関数) が
必要とした時にはいつでも呼びだされます。したがって、グローバルを完全に
禁止することも安全なサブセットに制限することも可能です。

これは、一部の安全なクラスについてのみ "builtins" モジュールからロード
することを許可する unpickler の例です:

   import builtins
   import io
   import pickle

   safe_builtins = {
       'range',
       'complex',
       'set',
       'frozenset',
       'slice',
   }

   class RestrictedUnpickler(pickle.Unpickler):

       def find_class(self, module, name):
           # builtins 内の安全なクラスだけを許可する。
           if module == "builtins" and name in safe_builtins:
               return getattr(builtins, name)
           # それ以外はすべて禁止する。
           raise pickle.UnpicklingError("global '%s.%s' is forbidden" %
                                        (module, name))

   def restricted_loads(s):
       """pickle.loads() に相当する補助関数。"""
       return RestrictedUnpickler(io.BytesIO(s)).load()

この unpickler が働く使用例は次のように意図されます:

   >>> restricted_loads(pickle.dumps([1, 2, range(15)]))
   [1, 2, range(0, 15)]
   >>> restricted_loads(b"cos\nsystem\n(S'echo hello world'\ntR.")
   Traceback (most recent call last):
     ...
   pickle.UnpicklingError: global 'os.system' is forbidden
   >>> restricted_loads(b'cbuiltins\neval\n'
   ...                  b'(S\'getattr(__import__("os"), "system")'
   ...                  b'("echo hello world")\'\ntR.')
   Traceback (most recent call last):
     ...
   pickle.UnpicklingError: global 'builtins.eval' is forbidden

この例が示すように、非 pickle 化を認めるものに注意しなければなりません
。したがって、セキュリティが重要な場合は "xmlrpc.client" の marshal
API や、サードパーティのソリューションのような別の選択肢を考慮した方が
よいでしょう。


性能
====

新しい pickle プロトコル (プロトコル 2 以降) は、一般的ないくつかの機
能や組み込み型に対して効率的なバイナリエンコーディングを備えています。
また、"pickle" モジュールには、C で書かれた最適化処理があり、利用者が
意識せずに使えます。


使用例
======

最も単純なコードでは、"dump()" および "load()" 関数を使用してください
。

   import pickle

   # pickle がサポートするオブジェクトの任意の集まり。
   data = {
       'a': [1, 2.0, 3+4j],
       'b': ("character string", b"byte string"),
       'c': {None, True, False}
   }

   with open('data.pickle', 'wb') as f:
       # 利用できる最大のプロトコルバージョンで 'data' 辞書を pickle 化する。
       pickle.dump(data, f, pickle.HIGHEST_PROTOCOL)

次の例は、pickle 化されたデータを読み込みます。

   import pickle

   with open('data.pickle', 'rb') as f:
       # プロトコルバージョンは自動的に検出されるので、指定する必要はない。
       data = pickle.load(f)


コマンドライン・インターフェース
================================

"pickle" モジュールはコマンドラインからスクリプトとして呼び出すことが
でき、pickle ファイルの内容を表示します。 ただし、調べたい pickle ファ
イルが信頼できない情報源からのものである場合は、pickle バイトコードを
実行しない "-m pickletools" の方が安全です。 pickletools のコマンドラ
インでの使用 を参照してください。

   python -m pickle pickle_file [pickle_file ...]

次のオプションを受け付けます:

pickle_file

   読み込む pickle ファイル。 標準入力から読み込む場合は "-" を指定し
   ます。

参考:

  "copyreg" モジュール
     拡張型を登録するための Pickle インターフェース構成機構。

  "pickletools" モジュール
     pickle データの処理や分析を行うためのツール。

  "shelve" モジュール
     索引付きのオブジェクトのデータベース。 "pickle" を使います。

  "copy" モジュール
     オブジェクトの浅いコピーおよび深いコピー。

  "marshal" モジュール
     組み込み型の高性能な直列化。

-[ 脚注 ]-

[1] "marshal" モジュールと間違えないように注意してください。

[2] なぜ "lambda" 関数を pickle 化できないかというと、すべての
    "lambda" 関数は同じ名前: "<lambda>" を共有しているからです。

[3] 送出される例外は "ImportError" や "AttributeError" になるはずです
    が、他の例外も起こりえます。

[4] "copy" モジュールは、浅いコピーと深いコピーの操作にこのプロトコル
    を使用します。

[5] 英数文字に関する制限は、プロトコル 0 では永続的な ID が改行文字に
    よって区切られるという事実によります。そのため、永続的な ID に何ら
    かの改行文字が含まれると、結果として生じる pickle 化されたデータは
    判読不能になります。
