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 int
s 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.
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).
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.
Vous pouvez également trouver cela intéressant, avec quelques graphiques à comparer: http://kovshenin.com/archives/pickle-vs-json-which-is-faster/
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:
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.
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.
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.
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