Рассол или json?
Мне нужно немного сохранить на диск dict
объект, ключи которого имеют тип str
, а значения int
, а затем восстановить его. Что-то вроде этого:
{'juanjo': 2, 'pedro':99, 'other': 333}
Каков наилучший вариант и почему? Сериализовать его с помощью pickle
или с помощью simplejson
?
Я использую Python 2.6.
Ответы
Ответ 1
Если у вас нет требований к совместимости (например, вы просто собираетесь использовать данные с Python), а бинарный формат в порядке, перейдите к cPickle, который дает вам очень быструю сериализацию объектов Python.
Если вам нужна совместимость или вы хотите, чтобы текстовый формат сохранял ваши данные, перейдите в JSON (или какой-либо другой соответствующий формат в зависимости от ваших ограничений).
Ответ 2
Я предпочитаю JSON над рассолом для моей сериализации. Unpickling может запускать произвольный код, а использование pickle
для передачи данных между программами или хранения данных между сеансами - это отверстие безопасности. JSON не вводит дыру в систему безопасности и стандартизован, поэтому к данным могут быть доступны программы на разных языках, если вам когда-либо понадобится.
Ответ 3
Вы также можете найти это интересное, с некоторыми графиками для сравнения: http://kovshenin.com/archives/pickle-vs-json-which-is-faster/
Ответ 4
JSON или рассол? Как насчет JSON и мариновать! Вы можете использовать jsonpickle
. Он прост в использовании, и файл на диске читается, потому что он JSON.
http://jsonpickle.github.com/
Ответ 5
Если вы в первую очередь озабочены скоростью и пространством, используйте cPickle, потому что cPickle быстрее, чем JSON.
Если вас больше интересует интероперабельность, безопасность и/или читаемость для человека, используйте JSON.
Результаты тестов, упомянутые в других ответах, были записаны в 2010 году, а обновленные тесты в 2016 году - cpickle протокол 2 шоу:
- cPickle 3.8x более быстрая загрузка
- cPickle 1.5x быстрее чтение
- cКластировать немного меньшую кодировку
Воспроизведите это самостоятельно this gist, который основан на критерий Константина, на который ссылаются другие ответы, но используя cPickle с протоколом 2 вместо pickle и используя json вместо simplejson (поскольку json быстрее, чем simplejson), например
wget https://gist.github.com/jdimatteo/af317ef24ccf1b3fa91f4399902bb534/raw/03e8dbab11b5605bc572bc117c8ac34cfa959a70/pickle_vs_json.py
python pickle_vs_json.py
Результаты с python 2.7 на достойном процессоре Xeon 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 с протоколом рассола 3 еще быстрее.
Ответ 6
Лично я обычно предпочитаю JSON, потому что данные доступны для человека. Определенно, если вам нужно сериализовать то, что JSON не будет принимать, чем использовать pickle.
Но для большинства хранилищ данных вам не нужно сериализовать что-нибудь странное, а JSON намного проще и всегда позволяет вам открывать его в текстовом редакторе и самостоятельно проверять данные.
Скорость хорошая, но для большинства наборов данных разница незначительна; Python обычно не слишком быстр.
Ответ 7
Я пробовал несколько методов и выяснил, что использование cPickle с настройкой аргумента протокола метода дампов как: 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