web-dev-qa-db-ja.com

Pythonオブジェクトをpickle化できるのはいつですか

マルチプロセッシングモジュールを使用して、Pythonでかなりの量の並列処理を行っています。特定のオブジェクトはpickle化できる(したがって、multi-pで引数として渡される)ことができ、他のオブジェクトはできないことを知っています。

class abc():
    pass

a=abc()
pickle.dumps(a)
'ccopy_reg\n_reconstructor\np1\n(c__main__\nabc\np2\nc__builtin__\nobject\np3\nNtRp4\n.'

しかし、コードにはより大きなクラスがいくつかあり(12個程度のメソッド)、これが発生します。

a=myBigClass()
pickle.dumps(a)
Traceback (innermost last):
 File "<stdin>", line 1, in <module>
 File "/usr/apps/Python279/python-2.7.9-rhel5-x86_64/lib/python2.7/copy_reg.py", line 70, in _reduce_ex
raise TypeError, "can't pickle %s objects" % base.__name__
TypeError: can't pickle file objects

これはファイルオブジェクトではありませんが、他の場合には、基本的に「これをピクルスにできません」というメッセージが表示されます。

それで、ルールは何ですか?バイト数?階層の深さ?月の満ち欠け?

14
Paul Nelson

私はdillの作者です。 dillの一部として、ピクルスとそうでないもののかなり包括的なリストがあります。 Python 2.5–3.4のバージョンごとに実行でき、1つのフラグを変更することで、dillのピクルスまたはpickleのピクルスに合わせて調整できます。-を参照してください。 ここ および ここ

ピクルスとは何かに関する規則の根源(頭のてっぺんから):

  1. 参照によってオブジェクトの状態をキャプチャできますか(つまり、__main__で定義された関数とインポートされた関数)。 [それでは、はい]
  2. 特定のオブジェクトタイプに一般的な__getstate__および__setstate__ルールが存在しますか? [それでは、はい]
  3. Frameオブジェクトに依存していますか(つまり、GILとグローバル実行スタックに依存していますか)?イテレータは、選択解除時にイテレータを「再生」することにより、これに対する例外になりました。 [それでは、いいえ]
  4. オブジェクトインスタンスが間違ったクラスパスを指していませんか(つまり、クロージャ、Cバインディング、またはその他の__init__パス操作で定義されているため)? [それでは、いいえ]
  5. Pythonこれを許可することは危険であると見なされますか?[それでは、いいえ]

したがって、(5)は以前よりも普及していませんが、pickleの言語では依然としていくつかの永続的な効果があります。 dillは、ほとんどの場合、(1)、(2)、および(5)を削除しますが、それでも(3)と(4)の影響をかなり受けます。

私は何か他のものを忘れているかもしれませんが、一般的にそれらは根本的なルールだと思います。

multiprocessingのような特定のモジュールは、それらの機能にとって重要ないくつかのオブジェクトを登録します。 dillは、オブジェクトの大部分を言語で登録します。

dillmultiprocessingを使用するためmultiprocessingcPickleフォークが必要であり、dillは純粋なPythonのpickle化レジストリのみを拡張できます。忍耐力があれば、dill内の関連するすべてのcopy_reg関数を調べて、それらをcPickleモジュールに適用すると、さらに多くのピクルスを得ることができます-有能なmultiprocessingpickleに対してこれを行う簡単な(読み:1つのライナー)方法を見つけましたが、cPickleではありません。

4
Mike McKerns

docs から:

以下のタイプを漬けることができます:

  • NoneTrue、およびFalse
  • 整数、長整数、浮動小数点数、複素数
  • 通常のUnicode文字列
  • 選択可能なオブジェクトのみを含むタプル、リスト、セット、および辞書
  • モジュールのトップレベルで定義された関数
    • モジュールのトップレベルで定義された組み込み関数
  • モジュールのトップレベルで定義されているクラス
  • ___dict___または__getstate__()を呼び出した結果がpickle化可能なクラスのインスタンス(詳細については、pickleプロトコルのセクションを参照してください)。

ピクルできないオブジェクトをピクルしようとすると、PicklingError例外が発生します。これが発生した場合、不特定のバイト数が基になるファイルにすでに書き込まれている可能性があります。再帰性の高いデータ構造をピクルスしようとすると、最大再帰深度を超える可能性があります。この場合、RuntimeErrorが発生します。 sys.setrecursionlimit()を使用してこの制限を慎重に上げることができます。

7
icedtrees

一般的な経験則では、「論理」オブジェクトはピクルス化できますが、「リソース」オブジェクト(ファイル、ロック)は永続化/クローン化する意味がないため、ピクルス化できません。

2
shx2

アイスツリーの答えに加えて、これも docs から直接得られ、特別なメソッドobject.__getnewargs_ex__()object.__getnewargs__()object.__getstate__()object.__setstate__(state)

2
Julien Spronck