Acar atau json?

114

Saya perlu menyimpan ke disk sebuah dictobjek kecil yang kuncinya berjenis strdan nilainya adalah ints dan kemudian memulihkannya . Sesuatu seperti ini:

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

Apa pilihan terbaik dan mengapa? Serialisasi dengan pickleatau dengan simplejson?

Saya menggunakan Python 2.6.

Juanjo Conti
sumber
mengubahnya menjadi apa? Juga, dalam arti apa lebih baik ?
SilentGhost
10
Di 2.6 Anda tidak akan menggunakan simplejson, Anda akan menggunakan jsonmodul builtin (yang memiliki antarmuka yang persis sama).
Mike Graham
5
"terbaik"? Terbaik untuk apa? Mempercepat? Kompleksitas? Fleksibilitas? Biaya?
S. Lott
@Trilarion: YAML adalah superset dari JSON
Martin Thoma

Jawaban:

68

Jika Anda tidak memiliki persyaratan interoperabilitas (misalnya Anda hanya akan menggunakan data dengan Python) dan format biner baik-baik saja, gunakan cPickle yang memberi Anda serialisasi objek Python yang sangat cepat.

Jika Anda ingin interoperabilitas atau Anda ingin format teks untuk menyimpan data Anda, gunakan JSON (atau beberapa format lain yang sesuai tergantung pada batasan Anda).

Håvard S
sumber
48
JSON tampaknya lebih cepat dari cPickle.
mac
5
Jawaban saya menyoroti masalah yang menurut saya paling penting untuk dipertimbangkan saat memilih solusi mana pun. Saya tidak membuat klaim tentang menjadi lebih cepat dari yang lain. Jika JSON lebih cepat DAN cocok, gunakan JSON! (Yaitu, tidak ada alasan untuk tidak memilih.)
Håvard S
10
Maksud saya adalah: tidak ada alasan nyata untuk menggunakan cPickle(atau pickle) berdasarkan tempat Anda melalui JSON. Ketika saya pertama kali membaca jawaban Anda, saya pikir alasannya mungkin karena kecepatan, tetapi karena bukan ini masalahnya ... :)
mac
14
Tolok ukur yang dikutip oleh @mac hanya menguji string. Saya menguji str, int dan float secara terpisah dan menemukan bahwa json lebih lambat dari cPickle dengan serialisasi float, tetapi lebih cepat dengan unserialization float. Untuk int (dan str), json lebih cepat dua arah. Data dan kode: gist.github.com/marians/f1314446b8bf4d34e782
Marian
24
Protokol terbaru cPickle sekarang lebih cepat dari JSON. Komentar yang mendapat suara positif tentang JSON menjadi lebih cepat sudah usang beberapa tahun. stackoverflow.com/a/39607169/1007353
JDiMatteo
104

Saya lebih suka JSON daripada acar untuk serialisasi saya. Pemisahan dapat menjalankan kode arbitrer, dan menggunakan pickleuntuk mentransfer data antar program atau menyimpan data antar sesi adalah celah keamanan. JSON tidak memperkenalkan celah keamanan dan sudah terstandarisasi, sehingga data dapat diakses oleh program dalam bahasa yang berbeda jika diperlukan.

Mike Graham
sumber
Terima kasih. Pokoknya saya akan membuang dan memuat di program yang sama.
Juanjo Conti
2
Meskipun risiko keamanan mungkin rendah dalam aplikasi Anda saat ini, JSON memungkinkan Anda untuk menutup seluruhnya.
Mike Graham
4
Seseorang dapat membuat virus acar yang mengawetkan dirinya sendiri menjadi segala sesuatu yang menjadi acar setelah dimuat. Dengan json ini tidak mungkin.
Pengguna
2
Selain keamanan, JSON memiliki keuntungan tambahan yaitu memudahkan migrasi, sehingga Anda dapat memuat data yang disimpan oleh versi lama aplikasi Anda. Sementara itu Anda bisa menambahkan bidang, atau mengganti seluruh sub struktur. Menulis konverter seperti itu (migrasi) untuk dict / list sangatlah mudah, tetapi dengan Pickle Anda akan kesulitan memuatnya sejak awal, bahkan sebelum Anda berpikir untuk mengonversinya.
vog
2
Saya tidak memikirkan aspek ini (keamanan dan kemampuan objek acar untuk menjalankan kode arbitrer). Terima kasih telah menunjukkannya!
CaffeinatedMike
20

Jika Anda terutama mementingkan kecepatan dan ruang, gunakan cPickle karena cPickle lebih cepat daripada JSON.

Jika Anda lebih mementingkan interoperabilitas, keamanan, dan / atau keterbacaan manusia, gunakan JSON.


Hasil tes yang direferensikan dalam jawaban lain dicatat pada tahun 2010, dan tes yang diperbarui pada tahun 2016 dengan protokol cPickle 2 menunjukkan:

  • cPickle 3.8x memuat lebih cepat
  • cPickle 1.5x lebih cepat membaca
  • cPickle encoding sedikit lebih kecil

Reproduksi ini sendiri dengan intisari ini , yang didasarkan pada tolok ukur Konstantin yang dirujuk dalam jawaban lain, tetapi menggunakan cPickle dengan protokol 2 alih-alih acar, dan menggunakan json daripada simplejson (karena json lebih cepat daripada simplejson ), misalnya

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

Hasil dengan python 2.7 pada prosesor Xeon 2015 yang layak:

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 dengan protokol acar 3 bahkan lebih cepat.

JDiMatteo
sumber
11

JSON atau acar? Bagaimana dengan JSON dan acar! Anda bisa menggunakan jsonpickle. Mudah digunakan dan file di disk dapat dibaca karena ini JSON.

http://jsonpickle.github.com/

Paul Hildebrandt
sumber
2
Adakah yang telah membandingkan kinerjanya dengan opsi? Apakah itu sebanding dalam kinerja sebagai json mentah seperti yang terlihat di sini benfrederickson.com/dont-pickle-your-data ?
Josep Valls
Ini bukan tolok ukur yang luas, tetapi saya memiliki game yang sudah ada di mana ia menyimpan level menggunakan acar (python3). Saya ingin mencoba jsonpickle untuk aspek yang dapat dibaca manusia - namun tingkat penyimpanannya sayangnya jauh lebih lambat. 1597ms untuk jsonpickle dan 88ms atau acar biasa pada level save. Untuk beban rata, 1604ms untuk jsonpickle dan 388 untuk acar. Sayang sekali karena saya suka menyimpan yang dapat dibaca manusia.
Neil McGill
Saya menguji ini dalam sistem perdagangan kami, keterbacaan datang dengan sekitar 2x serialisasi + penalti kecepatan deserialisasi dibandingkan dengan acar. Bagus untuk hal lain.
nurettin
6

Saya telah mencoba beberapa metode dan menemukan bahwa menggunakan cPickle dengan menetapkan argumen protokol metode dumps sebagai: cPickle.dumps(obj, protocol=cPickle.HIGHEST_PROTOCOL)adalah metode dump tercepat.

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)

Keluaran:

pickle         :   0.847938 seconds
cPickle        :   0.810384 seconds
cPickle highest:   0.004283 seconds
json           :   1.769215 seconds
msgpack        :   0.270886 seconds
Ahmed Abobakr
sumber
4

Secara pribadi, saya biasanya lebih suka JSON karena datanya dapat dibaca manusia . Tentunya, jika Anda perlu membuat serialisasi sesuatu yang tidak akan diambil JSON, daripada menggunakan acar.

Tetapi untuk sebagian besar penyimpanan data, Anda tidak perlu membuat serialisasi apa pun yang aneh dan JSON jauh lebih mudah dan selalu memungkinkan Anda untuk membukanya di editor teks dan memeriksa datanya sendiri.

Kecepatannya bagus, tetapi untuk sebagian besar kumpulan data perbedaannya dapat diabaikan; Python umumnya tidak terlalu cepat.

rickcnagy
sumber
1
Benar. Namun untuk 100elemen dalam daftar, perbedaannya dapat diabaikan sepenuhnya oleh mata manusia. Sangat berbeda ketika bekerja dengan kumpulan data yang lebih besar.
rickcnagy