web-dev-qa-db-ja.com

Python:なぜピクルス?

私はピクルスを使用していてとても幸せでした、そして私はこの記事を見ました: あなたのデータをピクルスにしないでください

さらに読むと、次のようになります。

データをJSONとして保存するように切り替えましたが、ベストプラクティスについて知りたいと思いました。

これらすべての問題を考えると、いつピクルスを使用しますか?どのような特定の状況でそれを使用する必要がありますか?

29
emh

Pickleは、任意の関数を呼び出して任意のPythonオブジェクトを構築するため、安全ではありません。ただし、これにより、ほぼすべてのPythonオブジェクトを、何もせずにシリアル化することができます。ボイラープレートまたはホワイト/ブラックリスト(一般的なケース)。これは、一部のユースケースでは非常に望ましい方法です。

  • 実行時間は長いが単純なスクリプトを一時停止および再開するための、迅速で簡単なシリアル化。ここでは問題はありません。プログラムの状態をそのままダンプして、後でロードするだけです。
  • multiprocessingのように、任意のPythonデータを他のプロセスまたはコンピューターに送信します。セキュリティ上の懸念可能性があります適用されます(ただし、ほとんどは適用されません)、一般性絶対に必要であり、人間はそれを読む必要はありません。

他の場合では、JSONまたは別の制限的なデータモデルに自分のものをマッピングする作業を正当化するのに十分な欠点はありません。人間の可読性/安全性/言語間の互換性が必要になるとは思わないかもしれませんし、必要がないかもしれません。覚えておいてください、あなたはそれを必要としないでしょう。 JSONを使用することは正しいことです™が、正しいとは限りません。

あなたは私が「遅い」欠点を完全に無視したことに気付くでしょう。これは、部分的に誤解を招く可能性があるためです。Pickleは、JSONモデル(文字列、数値、配列、マップ)に完全に適合するデータでは確かに低速ですが、データがそのような場合は、他の理由でJSONを使用する必要があります。データがそのようになっていない場合(非常に可能性が高い)、オブジェクトをJSONデータに変換するために必要なカスタムコードと、JSONデータをに戻すために必要なカスタムコードも考慮する必要があります。オブジェクト。これにより、エンジニアリング作業と実行時のオーバーヘッドの両方が追加されます。これらは、ケースバイケースで定量化する必要があります。

19
user395760

Pickleには便利な利点があります。追加の作業なしで任意のオブジェクトグラフをシリアル化でき、かなり広範囲のPythonタイプで動作します。とはいえ、私にとっては珍しいことです。新しいコードでPickleを使用します。JSONの方がはるかにクリーンです。

4
Sneftel

私は通常、PickleもJSONも使用しませんが、 MessagePack 安全で高速であり、小さなサイズのシリアル化されたデータを生成します。

追加の利点は、他の言語で記述されたソフトウェアとデータを交換できることです(もちろん、JSONの場合も同様です)。

3
wzab

JSON vs. Pickle security :JSONは、unicode、int、float、NoneType、bool、list、およびdictのみをpickle化できます。クラスインスタンスなどのより高度なオブジェクトをピクルスにする場合は使用できません。これらの種類のピクルスについては、言語にとらわれないという希望はないことに注意してください。

また、cPickleの代わりにPickleを使用すると、速度の進行が部分的に解決されます。

1
hivert

いくつかのメソッドを試しましたが、ダンプメソッドのプロトコル引数を次のように設定してcPickleを使用すると、cPickle.dumps(obj, protocol=cPickle.HIGHEST_PROTOCOL)が最速のダンプメソッドであることがわかりました。

import msgpack
import json
import pickle
import timeit
import cPickle
import numpy as np

num_tests = 10

obj = np.random.normal(0.5, 1, [240, 320, 3])

command = 'pickle.dumps(obj)'
setup = 'from __main__ import pickle, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("pickle:  %f seconds" % result)

command = 'cPickle.dumps(obj)'
setup = 'from __main__ import cPickle, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("cPickle:   %f seconds" % result)


command = 'cPickle.dumps(obj, protocol=cPickle.HIGHEST_PROTOCOL)'
setup = 'from __main__ import cPickle, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("cPickle highest:   %f seconds" % result)

command = 'json.dumps(obj.tolist())'
setup = 'from __main__ import json, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("json:   %f seconds" % result)


command = 'msgpack.packb(obj.tolist())'
setup = 'from __main__ import msgpack, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("msgpack:   %f seconds" % result)

出力:

pickle         :   0.847938 seconds
cPickle        :   0.810384 seconds
cPickle highest:   0.004283 seconds
json           :   1.769215 seconds
msgpack        :   0.270886 seconds

そのため、カメラからサーバーへのビデオストリーミングなど、リアルタイムのパフォーマンスが必要な状況では、最高のダンププロトコルを備えたcPickleを好みます。

0
Ahmed Abobakr