Gurke oder json?

114

Ich muss ein kleines dictObjekt auf der Festplatte speichern, dessen Schlüssel vom Typ sind strund dessen Werte ints sind, und es dann wiederherstellen . Etwas wie das:

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

Was ist die beste Option und warum? Serialisieren Sie es mit pickleoder mit simplejson?

Ich benutze Python 2.6.

Juanjo Conti
quelle
in was umwandeln? Und in welchem ​​Sinne besser ?
SilentGhost
10
In 2.6 würden Sie nicht verwenden simplejson, Sie würden das eingebaute jsonModul verwenden (das genau die gleiche Schnittstelle hat).
Mike Graham
5
"Beste"? Am besten für was? Geschwindigkeit? Komplexität? Flexibilität? Kosten?
S.Lott
@ Trilarion: YAML ist eine Obermenge von JSON
Martin Thoma

Antworten:

68

Wenn Sie keine Interoperabilitätsanforderungen haben (z. B. werden Sie die Daten nur mit Python verwenden) und ein Binärformat in Ordnung ist, wählen Sie cPickle , mit dem Sie Python-Objekte wirklich schnell serialisieren können.

Wenn Sie Interoperabilität oder ein Textformat zum Speichern Ihrer Daten wünschen, wählen Sie JSON (oder ein anderes geeignetes Format, abhängig von Ihren Einschränkungen).

Håvard S.
quelle
48
JSON scheint schneller als cPickle zu sein.
Mac
5
Meine Antwort hebt die Bedenken hervor, die meiner Meinung nach bei der Auswahl einer der beiden Lösungen am wichtigsten sind. Ich behaupte nicht, dass einer schneller ist als der andere. Wenn JSON schneller und ansonsten geeignet ist, entscheiden Sie sich für JSON! (Dh es gibt keinen Grund für Ihre Ablehnung.)
Håvard S
10
Mein Punkt ist: Es gibt keinen wirklichen Grund für die Verwendung cPickle(oder pickle) basierend auf Ihren Räumlichkeiten über JSON. Als ich Ihre Antwort zum ersten Mal las, dachte ich, der Grund könnte Geschwindigkeit gewesen sein, aber da dies nicht der Fall ist ... :)
Mac
14
Der von @mac angegebene Benchmark testet nur Zeichenfolgen. Ich habe str, int und float separat getestet und festgestellt, dass json bei der Float-Serialisierung langsamer als cPickle ist, bei der Float-Unserialisierung jedoch schneller. Für int (und str) ist json in beide Richtungen schneller. Daten und Code: gist.github.com/marians/f1314446b8bf4d34e782
Marian
24
Das neueste Protokoll von cPickle ist jetzt schneller als JSON. Der hochgestimmte Kommentar, dass JSON schneller ist, ist um einige Jahre veraltet. stackoverflow.com/a/39607169/1007353
JDiMatteo
104

Für meine Serialisierung bevorzuge ich JSON gegenüber Pickle. Das Aufheben der Auswahl kann beliebigen Code ausführen, und die Verwendung picklezum Übertragen von Daten zwischen Programmen oder zum Speichern von Daten zwischen Sitzungen ist eine Sicherheitslücke. JSON führt keine Sicherheitslücke ein und ist standardisiert, sodass Programme in verschiedenen Sprachen auf die Daten zugreifen können, falls dies jemals erforderlich sein sollte.

Mike Graham
quelle
Vielen Dank. Wie auch immer, ich werde im selben Programm ausgeben und laden.
Juanjo Conti
2
Obwohl die Sicherheitsrisiken in Ihrer aktuellen Anwendung möglicherweise gering sind, können Sie mit JSON das Ganze vollständig schließen.
Mike Graham
4
Man kann einen Gurkenvirus erzeugen, der sich in alles einfügt, was nach dem Laden eingelegt wird. Mit json ist das nicht möglich.
Benutzer
2
Neben der Sicherheit bietet JSON den zusätzlichen Vorteil, dass Migrationen einfach sind, sodass Sie Daten laden können, die von einer älteren Version Ihrer Anwendung gespeichert wurden. In der Zwischenzeit hätten Sie ein Feld hinzufügen oder eine ganze Unterstruktur ersetzen können. Das Schreiben eines solchen Konverters (Migration) für Diktat / Liste ist unkompliziert, aber mit Pickle fällt es Ihnen zunächst schwer, ihn zu laden, bevor Sie überhaupt an eine Konvertierung denken können.
Vog
2
Ich hatte nicht über diesen Aspekt nachgedacht (Sicherheit und die Fähigkeit von eingelegten Objekten, beliebigen Code auszuführen). Vielen Dank für den Hinweis!
CaffeinatedMike
20

Wenn Sie sich hauptsächlich mit Geschwindigkeit und Platz befassen, verwenden Sie cPickle, da cPickle schneller als JSON ist.

Wenn Sie sich mehr mit Interoperabilität, Sicherheit und / oder Lesbarkeit befassen, verwenden Sie JSON.


Die Testergebnisse, auf die in anderen Antworten verwiesen wird, wurden 2010 aufgezeichnet, und die aktualisierten Tests 2016 mit dem cPickle- Protokoll 2 zeigen:

  • cPickle 3.8x schnelleres Laden
  • cPickle 1,5x schnelleres Lesen
  • cPickle etwas kleinere Codierung

Reproduzieren Sie dies selbst mit diesem Kern , der auf dem Konstantin-Benchmark basiert, auf den in anderen Antworten verwiesen wird, aber cPickle mit Protokoll 2 anstelle von pickle und json anstelle von simplejson verwendet (da json schneller als simplejson ist ), z

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

Ergebnisse mit Python 2.7 auf einem anständigen Xeon-Prozessor 2015:

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 mit Pickle-Protokoll 3 ist noch schneller.

JDiMatteo
quelle
11

JSON oder Gurke? Wie wäre es mit JSON und Gurke! Sie können verwenden jsonpickle. Es ist einfach zu bedienen und die Datei auf der Festplatte ist lesbar, da es sich um JSON handelt.

http://jsonpickle.github.com/

Paul Hildebrandt
quelle
2
Hat jemand seine Leistung mit den Optionen verglichen? Ist es in der Leistung vergleichbar mit Raw Json, wie hier zu sehen ? Benfrederickson.com/dont-pickle-your-data ?
Josep Valls
Dies ist kein weitreichender Benchmark, aber ich hatte ein vorhandenes Spiel, in dem die Levels mit pickle (python3) gespeichert wurden. Ich wollte jsonpickle für den vom Menschen lesbaren Aspekt ausprobieren - allerdings waren die Level-Speicherungen leider viel langsamer. 1597ms für jsonpickle und 88ms oder normales pickle auf level save. Für ebene Belastung 1604 ms für jsonpickle und 388 ms für pickle. Schade, wie ich die menschlich lesbaren Paraden mag.
Neil McGill
Ich habe dies in unserem Handelssystem getestet. Die Lesbarkeit ist mit etwa 2x Serialisierung + Deserialisierungsgeschwindigkeit im Vergleich zu Pickle verbunden. Großartig für alles andere.
Nurettin
6

Ich habe verschiedene Methoden ausprobiert und festgestellt, dass die Verwendung von cPickle mit dem Festlegen des Protokollarguments cPickle.dumps(obj, protocol=cPickle.HIGHEST_PROTOCOL)der Dump-Methode als: die schnellste Dump-Methode ist.

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)

Ausgabe:

pickle         :   0.847938 seconds
cPickle        :   0.810384 seconds
cPickle highest:   0.004283 seconds
json           :   1.769215 seconds
msgpack        :   0.270886 seconds
Ahmed Abobakr
quelle
4

Persönlich bevorzuge ich im Allgemeinen JSON, da die Daten für Menschen lesbar sind . Auf jeden Fall, wenn Sie etwas serialisieren müssen, das JSON nicht akzeptiert, verwenden Sie pickle.

Für die meisten Datenspeicher müssen Sie jedoch nichts Seltsames serialisieren, und JSON ist viel einfacher und ermöglicht es Ihnen, es immer in einem Texteditor zu öffnen und die Daten selbst zu überprüfen.

Die Geschwindigkeit ist gut, aber für die meisten Datensätze ist der Unterschied vernachlässigbar. Python ist im Allgemeinen sowieso nicht zu schnell.

Rickcnagy
quelle
1
Wahr. Bei 100Elementen in einer Liste ist der Unterschied für das menschliche Auge jedoch völlig vernachlässigbar. Definitiv anders bei der Arbeit mit größeren Datensätzen.
Rickcnagy