web-dev-qa-db-fra.com

Pickle ou JSON?

J'ai besoin de sauvegarder sur le disque un petit objet dict dont les clés sont du type str et dont les valeurs sont ints puis le récupérer. Quelque chose comme ça:

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

Quelle est la meilleure option et pourquoi? Sérialisez-le avec pickle ou avec simplejson?

J'utilise Python 2.6.

106
Juanjo Conti

Si vous n’avez aucune exigence d’interopérabilité (par exemple, vous allez simplement utiliser les données avec Python) et qu’un format binaire convient, utilisez cPickle , ce qui vous donne une rapidité sans faille Python sérialisation d'objet.

Si vous souhaitez une interopérabilité ou un format de texte pour stocker vos données, utilisez JSON (ou un autre format approprié en fonction de vos contraintes).

64
Håvard S

Je préfère JSON à Pickle pour ma sérialisation. Unpickling peut exécuter du code arbitraire, et utiliser pickle pour transférer des données entre programmes ou stocker des données entre des sessions constitue un trou de sécurité. JSON n'introduit pas de faille de sécurité et est normalisé. Ainsi, les programmes peuvent être consultés par des programmes dans différentes langues, le cas échéant.

93
Mike Graham

Vous pouvez également trouver cela intéressant, avec quelques graphiques à comparer: http://kovshenin.com/archives/pickle-vs-json-which-is-faster/

42
kovshenin

Si vous êtes principalement préoccupé par la vitesse et l’espace, utilisez cPickle car cPickle est plus rapide que JSON.

Si vous êtes plus préoccupé par l'interopérabilité, la sécurité et/ou la lisibilité humaine, utilisez JSON.


Les résultats des tests référencés dans d'autres réponses ont été enregistrés en 2010, et les tests mis à jour en 2016 avec cPickle protocole 2 montrent:

  • cPickle 3.8x chargement plus rapide
  • cPickle 1.5x lecture plus rapide
  • cPickle encodage légèrement plus petit

Reproduisez-le vous-même avec this Gist , qui est basé sur le référence de Konstantin référencé dans d'autres réponses, mais en utilisant cPickle avec le protocole 2 au lieu de pickle, et en utilisant json au lieu de simplejson ( depuis json est plus rapide que simplejson ), par exemple.

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

Résultats avec python 2.7 sur un processeur Xeon 2015 décent:

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 avec le protocole de pickle 3 est encore plus rapide.

19
JDiMatteo

JSON ou cornichon? Que diriez-vous de JSON et cornichon! Vous pouvez utiliser jsonpickle. Il est facile à utiliser et le fichier sur disque est lisible car il s’agit de JSON.

http://jsonpickle.github.com/

11
Paul Hildebrandt

Personnellement, je préfère généralement JSON car les données sont lisibles par l'homme. Si vous avez besoin de sérialiser quelque chose que JSON ne prendra pas, utilisez pickle.

Mais pour la plupart des données stockées, vous n’aurez besoin de rien sérialiser et JSON est beaucoup plus facile et vous permet toujours de l’ouvrir dans un éditeur de texte et de vérifier les données vous-même.

La vitesse est bonne, mais pour la plupart des jeux de données, la différence est négligeable. Python n'est généralement pas trop rapide de toute façon.

4
rickcnagy

J'ai essayé plusieurs méthodes et découvert que l'utilisation de cPickle avec la définition de l'argument de protocole de la méthode dumps comme suit: cPickle.dumps(obj, protocol=cPickle.HIGHEST_PROTOCOL) est la méthode de vidage la plus rapide.

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)

Sortie:

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