マルチプロセッシングモジュールを使用して、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
これはファイルオブジェクトではありませんが、他の場合には、基本的に「これをピクルスにできません」というメッセージが表示されます。
それで、ルールは何ですか?バイト数?階層の深さ?月の満ち欠け?
私はdill
の作者です。 dill
の一部として、ピクルスとそうでないもののかなり包括的なリストがあります。 Python 2.5–3.4のバージョンごとに実行でき、1つのフラグを変更することで、dill
のピクルスまたはpickle
のピクルスに合わせて調整できます。-を参照してください。 ここ および ここ 。
ピクルスとは何かに関する規則の根源(頭のてっぺんから):
__main__
で定義された関数とインポートされた関数)。 [それでは、はい]__getstate__
および__setstate__
ルールが存在しますか? [それでは、はい]Frame
オブジェクトに依存していますか(つまり、GILとグローバル実行スタックに依存していますか)?イテレータは、選択解除時にイテレータを「再生」することにより、これに対する例外になりました。 [それでは、いいえ]__init__
パス操作で定義されているため)? [それでは、いいえ]したがって、(5)は以前よりも普及していませんが、pickle
の言語では依然としていくつかの永続的な効果があります。 dill
は、ほとんどの場合、(1)、(2)、および(5)を削除しますが、それでも(3)と(4)の影響をかなり受けます。
私は何か他のものを忘れているかもしれませんが、一般的にそれらは根本的なルールだと思います。
multiprocessing
のような特定のモジュールは、それらの機能にとって重要ないくつかのオブジェクトを登録します。 dill
は、オブジェクトの大部分を言語で登録します。
dill
はmultiprocessing
を使用するためmultiprocessing
のcPickle
フォークが必要であり、dill
は純粋なPythonのpickle化レジストリのみを拡張できます。忍耐力があれば、dill
内の関連するすべてのcopy_reg
関数を調べて、それらをcPickle
モジュールに適用すると、さらに多くのピクルスを得ることができます-有能なmultiprocessing
。 pickle
に対してこれを行う簡単な(読み:1つのライナー)方法を見つけましたが、cPickle
ではありません。
docs から:
以下のタイプを漬けることができます:
None
、True
、およびFalse
- 整数、長整数、浮動小数点数、複素数
- 通常のUnicode文字列
- 選択可能なオブジェクトのみを含むタプル、リスト、セット、および辞書
- モジュールのトップレベルで定義された関数
- モジュールのトップレベルで定義された組み込み関数
- モジュールのトップレベルで定義されているクラス
- _
__dict__
_または__getstate__()
を呼び出した結果がpickle化可能なクラスのインスタンス(詳細については、pickleプロトコルのセクションを参照してください)。ピクルできないオブジェクトをピクルしようとすると、
PicklingError
例外が発生します。これが発生した場合、不特定のバイト数が基になるファイルにすでに書き込まれている可能性があります。再帰性の高いデータ構造をピクルスしようとすると、最大再帰深度を超える可能性があります。この場合、RuntimeError
が発生します。sys.setrecursionlimit()
を使用してこの制限を慎重に上げることができます。
一般的な経験則では、「論理」オブジェクトはピクルス化できますが、「リソース」オブジェクト(ファイル、ロック)は永続化/クローン化する意味がないため、ピクルス化できません。
アイスツリーの答えに加えて、これも docs から直接得られ、特別なメソッドobject.__getnewargs_ex__()
、object.__getnewargs__()
、object.__getstate__()
、object.__setstate__(state)