web-dev-qa-db-ja.com

ピクルスまたはjson?

キーがdict型で値がstrsである小さなintオブジェクトをディスクに保存し、それを復元する必要があります。このようなもの:

{'juanjo': 2, 'pedro':99, 'other': 333}

最適なオプションとその理由は何ですか? pickleまたはsimplejsonでシリアル化しますか?

私はPython 2.6。

106
Juanjo Conti

相互運用性の要件がなく(たとえば、Pythonでデータを使用するだけで)、バイナリ形式で問題ない場合は、 cPickle を使用して、高速のPythonオブジェクトのシリアル化。

相互運用性が必要な場合、またはデータを保存するテキスト形式が必要な場合は、JSON(または制約に応じて他の適切な形式)を使用します。

64
Håvard S

シリアル化には、pickleよりJSONの方が好きです。ピックル解除は任意のコードを実行でき、pickleを使用してプログラム間でデータを転送したり、セッション間でデータを保存したりすることはセキュリティホールです。 JSONはセキュリティホールを導入せず、標準化されているため、必要に応じて異なる言語のプログラムからデータにアクセスできます。

93
Mike Graham

また、比較するためのいくつかのグラフを使用して、これを興味深いと思うかもしれません: http://kovshenin.com/archives/pickle-vs-json-which-is-faster/

42
kovshenin

主に速度とスペースに関心がある場合、cPickleはJSONよりも高速であるため、cPickleを使用します。

相互運用性、セキュリティ、および/または人間の可読性に関心がある場合は、JSONを使用してください。


他の回答で参照されているテスト結果は2010年に記録され、2016年にcPickle protocol 2 を使用して更新されたテストは次のとおりです。

  • cPickle 3.8倍高速な読み込み
  • cPickle 1.5倍高速な読み取り
  • cPickleわずかに小さいエンコード

this Gist でこれを再現します。これは、他の回答で参照されている Konstantinのベンチマーク に基づいていますが、pickleの代わりにプロトコル2でcPickleを使用し、simplejsonの代わりにjsonを使用します( jsonはsimplejson)より速いため、例えば.

wget https://Gist.github.com/jdimatteo/af317ef24ccf1b3fa91f4399902bb534/raw/03e8dbab11b5605bc572bc117c8ac34cfa959a70/pickle_vs_json.py
python pickle_vs_json.py

2015年のまともなXeonプロセッサでpython 2.7を使用した結果:

Dir Entries Method  Time    Length

dump    10  JSON    0.017   1484510
load    10  JSON    0.375   -
dump    10  Pickle  0.011   1428790
load    10  Pickle  0.098   -
dump    20  JSON    0.036   2969020
load    20  JSON    1.498   -
dump    20  Pickle  0.022   2857580
load    20  Pickle  0.394   -
dump    50  JSON    0.079   7422550
load    50  JSON    9.485   -
dump    50  Pickle  0.055   7143950
load    50  Pickle  2.518   -
dump    100 JSON    0.165   14845100
load    100 JSON    37.730  -
dump    100 Pickle  0.107   14287900
load    100 Pickle  9.907   -

pickleプロトコル3を使用したPython 3.4はさらに高速です。

19
JDiMatteo

JSONまたはピクルス? JSONandpickleはどうでしょう! jsonpickleを使用できます。使いやすく、ディスク上のファイルはJSONであるため読み取り可能です。

http://jsonpickle.github.com/

11

個人的には、データが人間が読み取れるであるため、私は一般的にJSONを好みます。間違いなく、JSONが受け取らないものをシリアル化する必要がある場合は、pickleを使用します。

しかし、ほとんどのデータストレージでは、奇妙なものをシリアル化する必要はなく、JSONははるかに簡単であり、常にテキストエディターで開いて自分でデータをチェックアウトできます。

速度は素晴らしいですが、ほとんどのデータセットでは違いは無視できます。 Python一般に、とにかく速すぎません。

4
rickcnagy

私はいくつかの方法を試しましたが、cPickleを使用して、dumpsメソッドのプロトコル引数を次のように設定していることがわかりました。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
4
Ahmed Abobakr