ピクルスかjson?


114

dictキーがタイプstrで値がints ある小さなオブジェクトをディスクに保存してから、回復する必要があります。このようなもの:

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

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

Python 2.6を使用しています。


それを何に変換しますか?また、どのような意味で良いですか?
SilentGhost 2010

10
2.6 simplejsonでは、を使用せず、組み込みjsonモジュール(まったく同じインターフェースを持つ)を使用します。
マイクグラハム

5
"ベスト"?何に最適ですか?速度?複雑?柔軟性?費用?
S.Lott、2013


回答:


68

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

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


48
JSON cPickle より速いようです。
Mac

5
私の回答は、どちらのソリューションを選択するときにも検討することが最も重要だと思う懸念を強調しています。私はどちらが他よりも速いという主張はしません。JSONの方が高速で、それ以外の点で適切な場合は、JSONを使用してください。(つまり、あなたの反対票を投じる理由はありません。)
HåvardS 2012

10
私の要点は、JSON経由で前提に基づいてcPickle(またはpickle)使用する本当の理由はありません。私が最初にあなたの答えを読んだとき、私は理由がスピードかもしれないと思ったが、これはそうではないので... :)
mac

14
@macが引用するベンチマークは文字列のみをテストします。str、int、floatを個別にテストしたところ、jsonはfloatシリアル化ではcPickleよりも低速ですが、float非シリアル化では高速であることがわかりました。int(およびstr)の場合、jsonはどちらの場合も高速です。データとコード:gist.github.com/marians/f1314446b8bf4d34e782
Marian

24
cPickleの最新プロトコルは、JSONより高速になりました。JSONの高速化についての賛成投票は数年で古くなっています。 stackoverflow.com/a/39607169/1007353
JDiMatteo 2016

104

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


ありがとう。とにかく、同じプログラムでダンプとロードを行います。
Juanjo Conti

2
現在のアプリケーションではセキュリティリスクは低いかもしれませんが、JSONを使用すると、全体を完全に閉じることができます。
マイクグラハム、

4
ロード後にピクルスにされるすべてのものにピクルス化するピクルスウイルスを作成できます。jsonではこれは不可能です。
ユーザーの

2
セキュリティの他に、JSONには移行が簡単になるという追加の利点があるため、古いバージョンのアプリケーションによって保存されたデータをロードできます。一方、フィールドを追加したり、サブ構造全体を置き換えたりすることができます。dict / list用のそのようなコンバーター(マイグレーション)を書くことは簡単ですが、Pickleを使用すると、変換を考える前に、そもそもそれをロードするのが困難になります。
2017年

2
私はこの側面(セキュリティとpickle化されたオブジェクトが任意のコードを実行する機能)については考えていませんでした。指摘してくれてありがとう!
CaffeinatedMike


20

主に速度とスペースに関心がある場合は、cPickleを使用してください。cPickleはJSONよりも高速だからです。

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


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

  • cPickle 3.8倍の高速読み込み
  • cPickle 1.5x高速読み取り
  • cPickleわずかに小さいエンコーディング

他の回答で参照されている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   -

Python 3.4とpickleプロトコル3はさらに高速です。


11

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

http://jsonpickle.github.com/


2
オプションに対するパフォーマンスをベンチマークした人はいますか?ここでbenfrederickson.com/dont-pickle-your-dataを見ると、生のjsonと同等のパフォーマンスですか?
Josep Valls 2016

これは広範囲のベンチマークではありませんが、pickle(python3)を使用してレベルを保存する既存のゲームがありました。人間が読める形式でjsonpickleを試したかったのですが、レベルの保存が悲しいことにはるかに遅くなりました。jsonpickleで1597ms、レベル保存で88msまたは通常のピクル。レベルロードの場合、jsonpickleで1604ms、pickleで388ms。私が人間が読める保存が好きなのは残念です。
Neil McGill

私のトレーディングシステムでこれをテストしました。読みやすさは、ピクルスと比較して約2倍のシリアライゼーション+デシリアライゼーション速度のペナルティを伴います。しかし、他のすべてに最適です。
ヌレティン

6

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

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

個人的には、データは人間が読めるので、私は一般的にJSONを好みます。もちろん、JSONで処理できないものをシリアル化する必要がある場合は、pickleを使用してください。

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

速度は優れていますが、ほとんどのデータセットではその違いは無視できます。とにかく、Pythonは一般的に高速ではありません。



1
そうだね。しかし100、リストの要素の場合、その違いは人間の目では完全に無視できます。より大きなデータセットを扱う場合は、明らかに異なります。
rickcnagy 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.