Рассол или JSON?


мне нужно сохранить на диск немного dict объект, ключи которого имеют тип str и значения ints а потом восстановить его. Что-то вроде этого:

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

что является лучшим вариантом и почему? Сериализуйте его с помощью pickle или simplejson?

Я использую Python 2.6.

7 81

7 ответов:

Если у вас нет никаких требований к совместимости (например, вы просто собираетесь использовать данные с Python), и двоичный формат в порядке, идите с cPickle что дает вам очень быструю сериализацию объектов Python.

Если вам нужна совместимость или вы хотите, чтобы текстовый формат хранил ваши данные, перейдите в JSON (или какой-либо другой подходящий формат в зависимости от ваших ограничений).

Я предпочитаю JSON над рассолом для моей сериализации. Распаковка может запускать произвольный код, а с помощью pickle для передачи данных между программами или хранение данных между сеансами-это дыра в безопасности. JSON не вводит дыру в безопасности и стандартизирован, поэтому данные могут быть доступны программами на разных языках, если вам когда-либо понадобится.

вы также можете найти это интересным, с некоторыми диаграммами для сравнения:http://kovshenin.com/archives/pickle-vs-json-which-is-faster/

Если вы в первую очередь связаны со скоростью и пространством, используйте cPickle, потому что cPickle быстрее, чем JSON.

Если вы больше заинтересованы в совместимости, безопасности и / или удобочитаемости человека, то используйте JSON.


результаты тестов, на которые ссылаются в других ответах, были записаны в 2010 году, а обновленные тесты в 2016 году с cPickle протокол 2 показать:

  • cPickle 3.8 x быстрее загрузка
  • cPickle 1.5 x более быстрое чтение
  • cPickle немного меньше кодирования

воспроизвести это самостоятельно с в этом суть, который на основании Константина ссылается на другие ответы, но использует 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 на приличном процессоре 2015 Xeon:

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 с протоколом pickle 3 еще быстрее.

JSON или рассол? Как насчет JSON и огурчик! Вы можете использовать jsonpickle. Он прост в использовании, и файл на диске читается, потому что это JSON.

http://jsonpickle.github.com/

лично я обычно предпочитаю JSON, потому что данные удобочитаемое. Определенно, Если вам нужно сериализовать что-то, что JSON не возьмет, чем использовать pickle.

но для большинства хранилищ данных вам не нужно будет сериализовать что-то странное, а JSON намного проще и всегда позволяет вам открыть его в текстовом редакторе и проверить данные самостоятельно.

скорость хорошая, но для большинства наборов данных разница незначительна; Python обычно не слишком быстро в любом случае.

я попробовал несколько методов и обнаружил, что с помощью cPickle с установкой аргумента протокола метода dumps как: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