Pickle o Json?


114

Ho bisogno di salvare su disco un po ' dictoggetto cui chiavi sono di tipo stre valori sono ints e poi recuperarlo . Qualcosa come questo:

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

Qual è l'opzione migliore e perché? Serializzarlo con pickleo con simplejson?

Sto usando Python 2.6.


convertirlo in cosa? Inoltre, in che senso meglio ?
SilentGhost

10
Nella 2.6 non useresti simplejson, useresti il jsonmodulo integrato (che ha la stessa identica interfaccia).
Mike Graham

5
"migliore"? Meglio per cosa? Velocità? Complessità? Flessibilità? Costo?
S.Lott


Risposte:


68

Se non hai requisiti di interoperabilità (ad esempio, userai i dati con Python) e un formato binario va bene, vai con cPickle che ti dà la serializzazione degli oggetti Python molto veloce.

Se si desidera l'interoperabilità o si desidera un formato di testo per memorizzare i dati, utilizzare JSON (o un altro formato appropriato a seconda dei vincoli).


48
JSON sembra essere più veloce di cPickle.
mac

5
La mia risposta evidenzia le preoccupazioni che penso siano più importanti da considerare quando si sceglie una delle due soluzioni. Non pretendo che uno dei due sia più veloce dell'altro. Se JSON è più veloce E altrimenti adatto, vai con JSON! (Cioè, non c'è motivo per il tuo voto
negativo

10
Il punto è: non c'è un vero motivo per utilizzare cPickle(o pickle) in base alle tue premesse su JSON. Quando ho letto la tua risposta per la prima volta ho pensato che il motivo potesse essere la velocità, ma poiché non è così ... :)
mac

14
Il benchmark citato da @mac verifica solo le stringhe. Ho testato str, int e float separatamente e ho scoperto che json è più lento di cPickle con la serializzazione float, ma più veloce con la non serializzazione float. Per int (e str), json è più veloce in entrambi i modi. Dati e codice: gist.github.com/marians/f1314446b8bf4d34e782
Marian

24
L'ultimo protocollo di cPickle è ora più veloce di JSON. Il commento più votato sul fatto che JSON sia più veloce è obsoleto di alcuni anni. stackoverflow.com/a/39607169/1007353
JDiMatteo

104

Preferisco JSON rispetto a pickle per la mia serializzazione. Unpickling può eseguire codice arbitrario e l'utilizzo pickleper trasferire dati tra programmi o memorizzare dati tra sessioni è un buco di sicurezza. JSON non introduce una falla di sicurezza ed è standardizzato, quindi i dati possono essere accessibili da programmi in lingue diverse, se necessario.


Grazie. Ad ogni modo scaricherò e caricherò lo stesso programma.
Juanjo Conti

2
Sebbene i rischi per la sicurezza possano essere bassi nella tua attuale applicazione, JSON ti consente di chiudere completamente il tutto.
Mike Graham

4
Si può creare un virus sottaceto che si insinua in tutto ciò che viene messo in salamoia dopo essere stato caricato. Con json questo non è possibile.
Utente

2
Oltre alla sicurezza, JSON ha il vantaggio aggiuntivo di semplificare le migrazioni, quindi puoi caricare i dati salvati da una versione precedente dell'applicazione. Nel frattempo avresti potuto aggiungere un campo o sostituire un'intera sottostruttura. Scrivere un tale convertitore (migrazione) per dict / list è semplice, ma con Pickle avrai difficoltà a caricarlo in primo luogo, prima ancora di poter pensare di convertire.
vog

2
Non avevo pensato a questo aspetto (sicurezza e capacità per gli oggetti decapati di eseguire codice arbitrario). Grazie per la segnalazione!
CaffeinatedMike


20

Se sei principalmente interessato alla velocità e allo spazio, usa cPickle perché cPickle è più veloce di JSON.

Se sei più interessato all'interoperabilità, alla sicurezza e / o alla leggibilità umana, utilizza JSON.


I risultati dei test a cui si fa riferimento in altre risposte sono stati registrati nel 2010 e i test aggiornati nel 2016 con il protocollo cPickle 2 mostrano:

  • cPickle 3,8 volte più veloce nel caricamento
  • cPickle 1,5 volte più veloce di lettura
  • cPickle una codifica leggermente più piccola

Riproducilo tu stesso con questa sintesi , che si basa sul benchmark di Konstantin a cui si fa riferimento in altre risposte, ma usando cPickle con protocollo 2 invece di pickle, e usando json invece di simplejson (poiché json è più veloce di simplejson ), ad es.

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

Risultati con python 2.7 su un processore Xeon 2015 decente:

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 con il protocollo pickle 3 è ancora più veloce.


11

JSON o sottaceto? Che ne dici di JSON e sottaceto! Puoi usare jsonpickle. È facile da usare e il file su disco è leggibile perché è JSON.

http://jsonpickle.github.com/


2
Qualcuno ha confrontato le sue prestazioni rispetto alle opzioni? È paragonabile in termini di prestazioni al json grezzo come visto qui benfrederickson.com/dont-pickle-your-data ?
Josep Valls

Questo non è un benchmark ad ampio raggio, ma avevo un gioco esistente in cui salvavo i livelli usando pickle (python3). Volevo provare jsonpickle per l'aspetto leggibile dall'uomo, tuttavia i salvataggi di livello erano purtroppo molto più lenti. 1597 ms per jsonpickle e 88 ms o sottaceto normale al salvataggio di livello. Per carico livellato, 1604 ms per jsonpickle e 388 per pickle. Peccato come mi piacciono i salvataggi leggibili dall'uomo.
Neil McGill

L'ho testato nel nostro sistema di trading, la leggibilità viene fornita con circa 2x serializzazione + penalità sulla velocità di deserializzazione rispetto al pickle. Ottimo per qualsiasi altra cosa, però.
nurettin

6

Ho provato diversi metodi e ho scoperto che l'uso di cPickle con l'impostazione dell'argomento del protocollo del metodo dump come: cPickle.dumps(obj, protocol=cPickle.HIGHEST_PROTOCOL)è il metodo di dump più veloce.

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)

Produzione:

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

4

Personalmente, generalmente preferisco JSON perché i dati sono leggibili dall'uomo . Sicuramente, se hai bisogno di serializzare qualcosa che JSON non accetterà, allora usa pickle.

Ma per la maggior parte dell'archiviazione dei dati, non è necessario serializzare nulla di strano e JSON è molto più semplice e ti consente sempre di aprirlo in un editor di testo e controllare i dati da solo.

La velocità è buona, ma per la maggior parte dei dataset la differenza è trascurabile; Python in genere non è troppo veloce comunque.



1
Vero. Ma per gli 100elementi di un elenco, la differenza è completamente trascurabile per l'occhio umano. Decisamente diverso quando si lavora con set di dati più grandi.
Rickcnagy
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.