2010-02-13 2 views
71

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

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

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

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

+0

преобразовать его к чему? Кроме того, в каком смысле * лучше *? – SilentGhost

+9

В 2.6 вы не использовали бы 'simplejson', вы бы использовали встроенный' json' модуль (который имеет тот же точный интерфейс). –

+5

"best"? Лучше всего для чего? Скорость? Сложность? Гибкость? Стоимость? –

ответ

45

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

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

+30

JSON [кажется, быстрее] (http://kovshenin.com/archives/ pickle-vs-json-which-is-faster /), чем cPickle. – mac

+3

В моем ответе освещаются проблемы, которые, по моему мнению, наиболее важны при выборе любого решения. Я не претендую на то, чтобы быть быстрее, чем другой. Если JSON работает быстрее и, в любом случае, подходит для JSON! (I.e., нет причин для вашего голосования.) –

+6

Моя точка зрения: нет никакой реальной причины использовать 'cPickle' (или' pickle') на основе вашего помещения над JSON. Когда я впервые прочитал ваш ответ, я подумал, что причиной может быть скорость, но поскольку это не так ... :) – mac

69

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

+0

Спасибо. Во всяком случае, я буду демпинг и погрузка в той же программе. –

+1

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

+3

Можно создать маринованный вирус, который замачивается во все, что маринован после загрузки. С помощью json это невозможно. – User

9

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

http://jsonpickle.github.com/

+2

Кто-нибудь сравнивает производительность с опциями? Является ли это сопоставимым по производительности как raw json, как показано здесь: http://www.benfrederickson.com/dont-pickle-your-data/? –

+0

Это не широкий диапазон тестов, но у меня была существующая игра, в которой он сохранял уровни, используя pickle (python3). Я хотел попробовать jsonpickle для читаемого человеком аспекта - однако уровень сохранения был, к сожалению, намного медленнее. 1597 мс для jsonpickle и 88 мс или регулярного рассола на уровне сохранения. Для уровня нагрузки 1604 мс для jsonpickle и 388 для рассола. Жаль, как мне нравится, когда человек читает. –

34

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

+5

Точно такое сравнение, которое я искал, спасибо! – mac

+0

В статье сравнивается производительность, относящаяся только к строкам. Вот скрипт, который вы можете запустить для тестирования строк, float и ints отдельно: https://gist.github.com/marians/f1314446b8bf4d34e782 – Marian

+3

[В Python 3.4, 'pickle' beats' json' в 'int',' str' и 'float'.] (http://stackoverflow.com/a/26860404/819417) –

4

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

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

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

+3

[В Python 3.4,' pickle' превышает вдвое быстрее, чем 'json'.] (http: // stackoverflow .com/a/26860404/819417) –

+1

Правда. Но для элементов '100' в списке разница совершенно ничтожна для человеческого глаза. Определенно отличается при работе с более крупными наборами данных. – rickcnagy

10

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

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


Результаты испытаний, указанные в других ответах были зафиксированы в 2010 году, и обновленные тесты в 2016 году с cPickle protocol 2 шоу:

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

Воспроизведите это себя this gist, который основан на Konstantin's benchmark ссылается в другие ответы, но с использованием cPickle с протоколом 2 вместо рассола, и используя 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 with pickle protocol 3 is even faster.

0

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