Соління або json?


114

Мені потрібно зберегти на диску маленький dictоб’єкт, чиї ключі мають тип strі значення ints, а потім відновити його . Щось на зразок цього:

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

Який найкращий варіант і чому? Серіалізувати його за допомогою pickleабо з simplejson?

Я використовую Python 2.6.


перетворити його в що? Також, в якому сенсі краще ?
SilentGhost

10
У 2.6 ви б не використовували simplejson, ви б використовували вбудований jsonмодуль (який має той самий точний інтерфейс).
Майк Грем

5
"найкращий"? Найкраще для чого? Швидкість? Складність? Гнучкість? Вартість?
S.Lott


Відповіді:


68

Якщо у вас немає жодних вимог щодо сумісності (наприклад, ви просто збираєтеся використовувати дані з Python), а двійковий формат прекрасний, перейдіть з cPickle, який дає вам дуже швидку серіалізацію об'єктів Python.

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


48
Здається, JSON швидше, ніж cPickle.
мак

5
У моїй відповіді підкреслюються проблеми, які, на мою думку, є найбільш важливими для врахування при виборі будь-якого рішення. Я не претендую на те, щоб бути швидшим за інших. Якщо JSON швидше І іншим чином підходить, ідіть з JSON! (Тобто, немає причини для вашого голосування.)
Håvard S

10
Моя думка: немає жодної реальної причини для використання cPickle(або pickle) на основі вашого приміщення в JSON. Коли я вперше прочитав вашу відповідь, я подумав, що причиною може бути швидкість, але оскільки це не так ... :)
мак

14
Тест, на який посилається @mac, лише тестує рядки. Я перевірив str, int та float окремо і з’ясував, що json повільніше, ніж cPickle з плаваючою серіалізацією, але швидше з несеріалізацією float. Для int (і str), json швидший обома способами. Дані та код: gist.github.com/marians/f1314446b8bf4d34e782
Маріан

24
Останній протокол cPickle тепер швидший, ніж JSON. Оголошений коментар про те, що JSON проходить швидше, застарів на кілька років. stackoverflow.com/a/39607169/1007353
JDiMatteo

104

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


Дякую. У будь-якому випадку я буду демпінгу та завантаження в тій же програмі.
Хуанхо Конті

2
Хоча ризики для безпеки можуть бути низькими у вашому поточному застосуванні, JSON дозволяє повністю закрити ціле.
Майк Грем

4
Можна створити маринований вірус, який маринує все, що маринується після завантаження. З json це неможливо.
Користувач

2
Окрім безпеки, JSON має додаткову перевагу в тому, що робить міграцію легкою, тому ви можете завантажувати дані, збережені в старій версії програми. Тим часом ви могли додати поле або замінити цілу підструктуру. Писати такий перетворювач (міграція) для dict / list прямо вперед, але з Pickle вам важко буде завантажувати його в першу чергу, перш ніж ви навіть можете думати про перетворення.
вог

2
Я не замислювався над цим аспектом (безпека та можливість маринованих об’єктів запускати довільний код). Дякуємо, що вказали на це!
CaffeinatedMike

43

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


1
У статті порівнюється продуктивність, що стосується лише рядків. Ось сценарій, який ви можете запустити, щоб окремо протестувати рядки, плаваючі та вбудовані елементи
Маріан


20

Якщо ви переймаєтесь швидкістю та простором, використовуйте cPickle, оскільки cPickle швидший, ніж JSON.

Якщо ви більше переймаєтесь інтероперабельністю, безпекою та / або читабельністю для людей, тоді використовуйте JSON.


Результати тестів, на які посилаються інші відповіді, були записані в 2010 році, а оновлені тести в 2016 році за допомогою протоколу 2 cPickle показують:

  • cPickle 3.8x швидше завантаження
  • cPickle на 1,5 рази швидше читання
  • cPickle трохи менше кодування

Відтворіть це самостійно за допомогою цієї суті , яка базується на орієнтирі Костянтина, на який посилається в інших відповідях, але використовуючи 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 на гідному процесорі 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 ще швидший.


11

JSON або соління? Як щодо JSON та соління! Можна використовувати jsonpickle. Він простий у використанні, а файл на диску читабельний, тому що це JSON.

http://jsonpickle.github.com/


2
Хтось орієнтував його на ефективність проти варіантів? Чи порівняна вона по продуктивності з сирим json, як це бачиться тут benfrederickson.com/dont-pickle-your-data ?
Хосеп Валлс

Це не широкий діапазон, але у мене була існуюча гра, де вона економила рівні, використовуючи соління (python3). Мені хотілося спробувати jsonpickle для людського читаного аспекту - однак збереження рівня були, на жаль, набагато повільнішими. 1597 мс для jsonpickle і 88 мс або звичайний соління на рівні економ. Для рівневого навантаження 1604 мс для jsonpickle і 388 для соління. Шкода, як мені подобається, що люди читають, економить.
Ніл Макгілл

Я перевірив це в нашій торговій системі, читабельність - це приблизно 2 рази серіалізація + штраф за швидкість десеріалізації порівняно з солінням. Хоча чудово для всього іншого.
Нуреттін

6

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

4

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

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

Швидкість приємна, але для більшості наборів даних різниця незначна; Python взагалі не надто швидкий.



1
Правда. Але для 100елементів у списку різниця абсолютно незначна для людського ока. Однозначно відрізняється при роботі з більшими наборами даних.
rickcnagy
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.