Turşu veya json?


114

dictAnahtarları türde strve değerleri ints olan küçük bir nesneyi diske kaydetmem ve sonra kurtarmam gerekiyor . Bunun gibi bir şey:

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

En iyi seçenek nedir ve neden? İle pickleveya ile seri hale getirilsin simplejsonmi?

Python 2.6 kullanıyorum.


neye çevirecek? Ayrıca, hangi anlamda daha iyi ?
SilentGhost

10
2.6'da simplejsonkullanmayacağınız, yerleşik jsonmodülü (aynı arayüze sahip olan) kullanırsınız.
Mike Graham

5
"en iyi"? Ne için en iyisi? Hız? Karmaşıklık? Esneklik? Maliyet?
S.Lott


@Trilarion: YAML,
Martin Thoma

Yanıtlar:


68

Herhangi bir birlikte çalışabilirlik gereksiniminiz yoksa (örneğin, verileri Python ile kullanacaksanız) ve ikili formatta sorun yoksa , size gerçekten hızlı Python nesne serileştirme sağlayan cPickle ile gidin .

Birlikte çalışabilirlik istiyorsanız veya verilerinizi depolamak için bir metin biçimi istiyorsanız, JSON (veya kısıtlamalarınıza bağlı olarak başka bir uygun biçim) kullanın.


48
JSON , cPickle'dan daha hızlı görünüyor .
mac

5
Cevabım, iki çözümden birini seçerken en önemli olduğunu düşündüğüm endişeleri vurguluyor. Ben de diğerinden daha hızlı olduğumu iddia etmiyorum. JSON daha hızlıysa VE başka şekilde uygunsa, JSON ile devam edin! (Yani,
olumsuz

10
Demek istediğim: JSON üzerinden tesislerinize bağlı olarak cPickle(veya pickle) kullanmak için gerçek bir neden yok . Cevabınızı ilk okuduğumda sebebin hız olabileceğini düşündüm, ama durum böyle olmadığından ... :)
mac 4'12

14
@Mac tarafından belirtilen kıyaslama yalnızca dizeleri test eder. Str, int ve float'ı ayrı ayrı test ettim ve json'un float serileştirme ile cPickle'dan daha yavaş, ancak float serileştirmeden daha hızlı olduğunu öğrendim. İnt (ve str) için json her iki yönde de daha hızlıdır. Veri ve kod: gist.github.com/marians/f1314446b8bf4d34e782
Marian

24
cPickle'ın en son protokolü artık JSON'dan daha hızlı. JSON'un daha hızlı olduğu hakkında oylanan yorum birkaç yıl geçerliliğini yitirdi. stackoverflow.com/a/39607169/1007353
JDiMatteo

104

Serileştirmem için turşu yerine JSON'u tercih ediyorum. Unpickling rastgele kod çalıştırabilir ve pickleprogramlar arasında veri aktarmak veya oturumlar arasında veri depolamak için kullanmak bir güvenlik açığıdır. JSON bir güvenlik açığı oluşturmaz ve standartlaştırılmıştır, böylece ihtiyaç duyduğunuzda verilere farklı dillerdeki programlar tarafından erişilebilir.


Teşekkürler. Her neyse, aynı programda damping ve yükleme yapacağım.
Juanjo Conti

2
Mevcut uygulamanızda güvenlik riskleri düşük olsa da JSON, tamamını tamamen kapatmanıza izin verir.
Mike Graham

4
Yüklendikten sonra turşu haline gelen her şeye kendi kendine bulaşan bir turşu virüsü yaratılabilir. JSON ile bu mümkün değildir.
Kullanıcı

2
Güvenlik dışında JSON, geçişleri kolaylaştırma ek avantajına sahiptir, böylece uygulamanızın eski bir sürümü tarafından kaydedilen verileri yükleyebilirsiniz. Bu arada bir alan ekleyebilir veya tüm bir alt yapıyı değiştirebilirdiniz. Dikte / liste için böyle bir dönüştürücü (taşıma) yazmak basittir, ancak Pickle ile dönüştürmeyi düşünmeden önce onu ilk etapta yüklemekte zorlanacaksınız.
vog

2
Bu yönü düşünmemiştim (güvenlik ve turşu nesnelerin rastgele kod çalıştırma yeteneği). Bunu belirttiğiniz için teşekkürler!
CaffeinatedMike


20

Öncelikle hız ve alanla ilgileniyorsanız, cPickle kullanın çünkü cPickle JSON'dan daha hızlıdır.

Birlikte çalışabilirlik, güvenlik ve / veya insan tarafından okunabilirlik ile daha fazla ilgileniyorsanız, JSON kullanın.


Diğer cevaplarda atıfta bulunulan test sonuçları 2010 yılında kaydedilmiştir ve 2016 yılında cPickle protokolü 2 ile güncellenmiş testler şunları göstermektedir:

  • cPickle 3,8 kat daha hızlı yükleme
  • cPickle 1,5 kat daha hızlı okuma
  • cPickle biraz daha küçük kodlama

Bu kendini yeniden bu ana fikri üzerine kuruludur, Konstantin adlı kriter diğer cevaplar başvurulan, ancak protokolün 2 yerine turşu ile cPickle kullanarak ve bunun yerine simplejson ait json kullanarak (beri json hızlı simplejson daha ), örneğin

wget https://gist.github.com/jdimatteo/af317ef24ccf1b3fa91f4399902bb534/raw/03e8dbab11b5605bc572bc117c8ac34cfa959a70/pickle_vs_json.py
python pickle_vs_json.py

İyi bir 2015 Xeon işlemci üzerinde python 2.7 sonuçları:

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   -

Turşu protokolü 3 ile Python 3.4 daha da hızlıdır.


11

JSON veya turşu? JSON ve turşuya ne dersin ! Kullanabilirsiniz jsonpickle. Kullanımı kolaydır ve diskteki dosya JSON olduğundan okunabilirdir.

http://jsonpickle.github.com/


2
Performansını seçeneklere göre karşılaştıran var mı? Performans açısından burada benfrederickson.com/dont-pickle-your-data görüldüğü gibi ham json ile karşılaştırılabilir mi?
Josep Valls

Bu geniş kapsamlı bir ölçüt değil, ancak turşu (python3) kullanarak seviyeleri kaydettiği mevcut bir oyunum vardı. İnsan tarafından okunabilir yönü için jsonpickle'ı denemek istedim - ancak kaydetme seviyesi ne yazık ki çok daha yavaştı. Jsonpickle ve 88ms için 1597ms veya seviye kaydetme üzerinde normal turşu. Seviye yükü için, jsonpickle için 1604ms ve turşu için 388ms. Ne yazık ki insan tarafından okunabilen kurtarır.
Neil McGill

Bunu ticaret sistemimizde test ettim, okunabilirlik turşu ile karşılaştırıldığında yaklaşık 2 kat serileştirme + seriyi kaldırma hız cezası ile geliyor. Yine de başka her şey için harika.
nurettin

6

Birkaç yöntem denedim ve dumps yönteminin protokol argümanını ayarlayarak cPickle kullanmanın cPickle.dumps(obj, protocol=cPickle.HIGHEST_PROTOCOL)en hızlı döküm yöntemi olduğunu öğrendim .

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)

Çıktı:

pickle         :   0.847938 seconds
cPickle        :   0.810384 seconds
cPickle highest:   0.004283 seconds
json           :   1.769215 seconds
msgpack        :   0.270886 seconds

4

Kişisel olarak, veriler insan tarafından okunabilir olduğu için genellikle JSON'u tercih ederim . Kesinlikle, JSON'un almayacağı bir şeyi serileştirmeniz gerekiyorsa, turşu kullanmak yerine.

Ancak çoğu veri depolaması için, tuhaf şeyleri seri hale getirmenize gerek kalmaz ve JSON çok daha kolaydır ve her zaman bir metin düzenleyicide açmanıza ve verileri kendiniz kontrol etmenize izin verir.

Hız iyidir, ancak çoğu veri kümesi için fark önemsizdir; Python genellikle zaten çok hızlı değildir.



1
Doğru. Ancak 100bir listedeki öğeler için , fark insan gözü için tamamen ihmal edilebilir. Daha büyük veri kümeleriyle çalışırken kesinlikle farklı.
rickcnagy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.