Рассол или 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 не вводит дыру в систему безопасности и стандартизован, поэтому к данным могут быть доступны программы на разных языках, если вам когда-либо понадобится.

Ответ 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