Quali sono le differenze tra i moduli json e simplejson Python?


381

Ho visto molti progetti usando simplejsonmodule invece di jsonmodule dalla Standard Library. Inoltre, ci sono molti simplejsonmoduli diversi . Perché utilizzare queste alternative, anziché quella nella libreria standard?

Risposte:


391

json viene simplejson aggiunto allo stdlib. Ma poiché è jsonstato aggiunto in 2.6, simplejsonha il vantaggio di lavorare su più versioni di Python (2.4+).

simplejsonviene inoltre aggiornato più frequentemente di Python, quindi se hai bisogno (o desideri) della versione più recente, è meglio usare simplejsonse stesso, se possibile.

Una buona pratica, secondo me, è usare l'uno o l'altro come fallback.

try:
    import simplejson as json
except ImportError:
    import json

2
Ora, se solo riuscissi a smettere di lamentarmi con i pyflakesredefinition of unused 'json'
James McMahon,

5
Non sono uguali né compatibili, simplejson ha un JSONDecodeError e json ha un ValueError
Bjorn

3
@BjornTipling JSONDecodeErrorè una sottoclasse diValueError
elhefe

30
Non sono d'accordo con la risposta di cui sopra supponendo che tu abbia un Python aggiornato. La libreria Json incorporata (un grande vantaggio !!!) in Python 2.7 è veloce come simplejson e ha meno bug unicode da rifiutare. Vedi risposta stackoverflow.com/a/16131316/78234
Tal Weiss

1
Sembra che il Python2.7 json abbia adottato simplejson v2.0.9 che è molto indietro rispetto all'attuale simplejson v3.6.5 al momento della scrittura. Ci sono molti miglioramenti che valgono l'importazione simplejson
Kenji Noguchi,

82

Non sono d'accordo con le altre risposte: la jsonlibreria integrata (in Python 2.7) non è necessariamente più lenta di simplejson. Inoltre non ha questo fastidioso bug unicode .

Ecco un semplice benchmark:

import json
import simplejson
from timeit import repeat

NUMBER = 100000
REPEAT = 10

def compare_json_and_simplejson(data):
    """Compare json and simplejson - dumps and loads"""
    compare_json_and_simplejson.data = data
    compare_json_and_simplejson.dump = json.dumps(data)
    assert json.dumps(data) == simplejson.dumps(data)
    result = min(repeat("json.dumps(compare_json_and_simplejson.data)", "from __main__ import json, compare_json_and_simplejson", 
                 repeat = REPEAT, number = NUMBER))
    print "      json dumps {} seconds".format(result)
    result = min(repeat("simplejson.dumps(compare_json_and_simplejson.data)", "from __main__ import simplejson, compare_json_and_simplejson", 
                 repeat = REPEAT, number = NUMBER))
    print "simplejson dumps {} seconds".format(result)
    assert json.loads(compare_json_and_simplejson.dump) == data
    result = min(repeat("json.loads(compare_json_and_simplejson.dump)", "from __main__ import json, compare_json_and_simplejson", 
                 repeat = REPEAT, number = NUMBER))
    print "      json loads {} seconds".format(result)
    result = min(repeat("simplejson.loads(compare_json_and_simplejson.dump)", "from __main__ import simplejson, compare_json_and_simplejson", 
                 repeat = REPEAT, number = NUMBER))
    print "simplejson loads {} seconds".format(result)


print "Complex real world data:" 
COMPLEX_DATA = {'status': 1, 'timestamp': 1362323499.23, 'site_code': 'testing123', 'remote_address': '212.179.220.18', 'input_text': u'ny monday for less than \u20aa123', 'locale_value': 'UK', 'eva_version': 'v1.0.3286', 'message': 'Successful Parse', 'muuid1': '11e2-8414-a5e9e0fd-95a6-12313913cc26', 'api_reply': {"api_reply": {"Money": {"Currency": "ILS", "Amount": "123", "Restriction": "Less"}, "ProcessedText": "ny monday for less than \\u20aa123", "Locations": [{"Index": 0, "Derived From": "Default", "Home": "Default", "Departure": {"Date": "2013-03-04"}, "Next": 10}, {"Arrival": {"Date": "2013-03-04", "Calculated": True}, "Index": 10, "All Airports Code": "NYC", "Airports": "EWR,JFK,LGA,PHL", "Name": "New York City, New York, United States (GID=5128581)", "Latitude": 40.71427, "Country": "US", "Type": "City", "Geoid": 5128581, "Longitude": -74.00597}]}}}
compare_json_and_simplejson(COMPLEX_DATA)
print "\nSimple data:"
SIMPLE_DATA = [1, 2, 3, "asasd", {'a':'b'}]
compare_json_and_simplejson(SIMPLE_DATA)

E i risultati sul mio sistema (Python 2.7.4, Linux 64-bit):

Dati complessi del mondo reale:
dump json 1,56666707993 secondi
dump simplejson 2,25638604164 secondi
carichi json 2,71256899834 secondi
carichi simplejson 1,29233884811 secondi

Dati semplici:
json dump 0,370109081268 secondi
simplejson dump 0,574181079865 secondi
json carica 0,422876119614 secondi
simplejson carica 0,270955085754 secondi

Per il dumping, jsonè più veloce di simplejson. Per il caricamento, simplejsonè più veloce.

Dato che attualmente sto creando un servizio Web, dumps()è più importante e è sempre preferibile utilizzare una libreria standard.

Inoltre, cjsonnon è stato aggiornato negli ultimi 4 anni, quindi non lo toccherei.


Questo è fuorviante. La mia risposta sotto spiega perché.
notbad.jpeg,

2
Sul mio PC Win7 (CPU i7), json(CPython 3.5.0) è il 68% | 45% più veloce su dump semplici | complessi e il 35% | 17% su carichi semplici | complessi rispetto a simplejsonv3.8.0 con speedup C usando il tuo codice di riferimento. Pertanto, non utilizzerei più Simplejson con questa configurazione.
martedì

1
Ho appena eseguito questo su Python 3.6.1 e jsonvince o è lo stesso per tutti i test. In effetti jsonè un po 'meno veloce del doppio del complesso test dei dump di dati del mondo reale!
CpILL,

27

Tutte queste risposte non sono molto utili perché sono sensibili al tempo .

Dopo aver fatto alcune mie ricerche ho scoperto che simplejsonè davvero più veloce di quello incorporato, se lo tieni aggiornato all'ultima versione.

pip/easy_installvolevo installare 2.3.2 su Ubuntu 12.04, ma dopo aver scoperto che l'ultima simplejsonversione è in realtà la 3.3.0, quindi l'ho aggiornata e ho riprovato i test del tempo.

  • simplejsonè circa 3 volte più veloce di quello incorporato jsonai carichi
  • simplejsonè circa il 30% più veloce di quello incorporato jsonnelle discariche

Disclaimer:

Le affermazioni di cui sopra sono in python-2.7.3 e simplejson 3.3.0 (con accelerazioni c) E per assicurarsi che anche la mia risposta non sia sensibile al tempo, è necessario eseguire i propri test per verificare poiché varia molto tra le versioni; non esiste una risposta facile che non sia sensibile al tempo.

Come sapere se gli speedup C sono abilitati in simplejson:

import simplejson
# If this is True, then c speedups are enabled.
print bool(getattr(simplejson, '_speedups', False))

AGGIORNAMENTO: Di recente mi sono imbattuto in una libreria chiamata ujson che sta eseguendo ~ 3 volte più velocemente rispetto simplejsonad alcuni test di base.


Grazie per aver menzionato Ujson. Questo mi porta ad un'altra libreria RapidJSON che sembra meglio mantenuta
MCMZL

"simplejson 3.3.0 (con accelerazioni c)" oh davvero? sii più onesto e provalo senza accelerazioni.
Reishin,

non usare ujson, è pieno di bug, perdite di memoria e crash e non è stato aggiornato da un po 'di tempo. L'abbiamo abbandonato e siamo passati a simplejson in quanto ha più funzionalità di json e viene aggiornato
amhr

21

Ho fatto il benchmarking di json, simplejson e cjson.

  • cjson è il più veloce
  • simplejson è quasi alla pari di cjson
  • json è circa 10 volte più lento di simplejson

http://pastie.org/1507411 :

$ python test_serialization_speed.py 
--------------------
   Encoding Tests
--------------------
Encoding: 100000 x {'m': 'asdsasdqwqw', 't': 3}
[      json] 1.12385 seconds for 100000 runs. avg: 0.011239ms
[simplejson] 0.44356 seconds for 100000 runs. avg: 0.004436ms
[     cjson] 0.09593 seconds for 100000 runs. avg: 0.000959ms

Encoding: 10000 x {'m': [['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19], ['0', 1, '2', 3, '4', 5, '6', 7, '8', 9, '10', 11, '12', 13, '14', 15, '16', 17, '18', 19]], 't': 3}
[      json] 7.76628 seconds for 10000 runs. avg: 0.776628ms
[simplejson] 0.51179 seconds for 10000 runs. avg: 0.051179ms
[     cjson] 0.44362 seconds for 10000 runs. avg: 0.044362ms

--------------------
   Decoding Tests
--------------------
Decoding: 100000 x {"m": "asdsasdqwqw", "t": 3}
[      json] 3.32861 seconds for 100000 runs. avg: 0.033286ms
[simplejson] 0.37164 seconds for 100000 runs. avg: 0.003716ms
[     cjson] 0.03893 seconds for 100000 runs. avg: 0.000389ms

Decoding: 10000 x {"m": [["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19], ["0", 1, "2", 3, "4", 5, "6", 7, "8", 9, "10", 11, "12", 13, "14", 15, "16", 17, "18", 19]], "t": 3}
[      json] 37.26270 seconds for 10000 runs. avg: 3.726270ms
[simplejson] 0.56643 seconds for 10000 runs. avg: 0.056643ms
[     cjson] 0.33007 seconds for 10000 runs. avg: 0.033007ms

6
Aggiungi un pastoe per il modulo di test effettivo.
Tal Weiss,

4
quali versioni di Python e le librerie in questione?
Anentropico

6
Questo non è più vero. json in python2.7 è miglioramenti delle prestazioni.
zengr,

11

Alcuni valori sono serializzati in modo diverso tra simplejson e json.

In particolare, le istanze di collections.namedtuplesono serializzate come matrici da jsonma come oggetti da simplejson. È possibile ignorare questo comportamento passando namedtuple_as_object=Falsea simplejson.dump, ma per impostazione predefinita i comportamenti non corrispondono.

>>> import collections, simplejson, json
>>> TupleClass = collections.namedtuple("TupleClass", ("a", "b"))
>>> value = TupleClass(1, 2)
>>> json.dumps(value)
'[1, 2]'
>>> simplejson.dumps(value)
'{"a": 1, "b": 2}'
>>> simplejson.dumps(value, namedtuple_as_object=False)
'[1, 2]'

7

Ho riscontrato un'incompatibilità dell'API, con Python 2.7 vs simplejson 3.3.1 sta nel fatto che l'output produca oggetti str o unicode. per esempio

>>> from json import JSONDecoder
>>> jd = JSONDecoder()
>>> jd.decode("""{ "a":"b" }""")
{u'a': u'b'}

vs

>>> from simplejson import JSONDecoder
>>> jd = JSONDecoder()
>>> jd.decode("""{ "a":"b" }""")
{'a': 'b'}

Se la preferenza è usare simplejson, questo può essere risolto forzando la stringa dell'argomento in unicode, come in:

>>> from simplejson import JSONDecoder
>>> jd = JSONDecoder()
>>> jd.decode(unicode("""{ "a":"b" }""", "utf-8"))
{u'a': u'b'}

La coercizione richiede la conoscenza del set di caratteri originale, ad esempio:

>>> jd.decode(unicode("""{ "a": "ξηθννββωφρες" }"""))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xce in position 8: ordinal not in range(128)

Questo non risolverà il problema 40


6

Un altro motivo per cui i progetti utilizzano simplejson è che il json incorporato non includeva originariamente i suoi accelerazioni in C, quindi la differenza di prestazioni era evidente.


5

Il jsonmodulo integrato è stato incluso in Python 2.6. Tutti i progetti che supportano le versioni di Python <2.6 devono avere un fallback. In molti casi, quel fallback è simplejson.



2

Il modulo simplejson è semplicemente 1,5 volte più veloce di json (Sul mio computer, con simplejson 2.1.1 e Python 2.7 x86).

Se lo desideri, puoi provare il benchmark: http://abral.altervista.org/jsonpickle-bench.zip Sul mio PC simplejson è più veloce di cPickle. Mi piacerebbe conoscere anche i tuoi benchmark!

Probabilmente, come detto Coady, la differenza tra simplejson e json è che simplejson include _speedups.c. Quindi, perché gli sviluppatori di Python non usano simplejson?


2

In python3, se hai una stringa di b'bytes', jsondevi avere .decode()il contenuto prima di poterlo caricare. simplejsonsi prende cura di questo in modo da poterlo fare simplejson.loads(byte_string).


Modificato nella versione 3.6: s ora può essere di tipo byte o bytearray. La codifica di input dovrebbe essere UTF-8, UTF-16 o UTF-32.
Mathieu Longtin,

1

jsonsembra più veloce che simplejsonin entrambi i casi di carichi e dump nell'ultima versione

Versioni testate:

  • python: 3.6.8
  • json: 2.0.9
  • simplejson: 3.16.0

risultati:

>>> def test(obj, call, data, times):
...   s = datetime.now()
...   print("calling: ", call, " in ", obj, " ", times, " times") 
...   for _ in range(times):
...     r = getattr(obj, call)(data)
...   e = datetime.now()
...   print("total time: ", str(e-s))
...   return r

>>> test(json, "dumps", data, 10000)
calling:  dumps  in  <module 'json' from 'C:\\Users\\jophine.antony\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\json\\__init__.py'>   10000  times
total time:  0:00:00.054857

>>> test(simplejson, "dumps", data, 10000)
calling:  dumps  in  <module 'simplejson' from 'C:\\Users\\jophine.antony\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\site-packages\\simplejson\\__init__.py'>   10000  times
total time:  0:00:00.419895
'{"1": 100, "2": "acs", "3.5": 3.5567, "d": [1, "23"], "e": {"a": "A"}}'

>>> test(json, "loads", strdata, 1000)
calling:  loads  in  <module 'json' from 'C:\\Users\\jophine.antony\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\json\\__init__.py'>   1000  times
total time:  0:00:00.004985
{'1': 100, '2': 'acs', '3.5': 3.5567, 'd': [1, '23'], 'e': {'a': 'A'}}

>>> test(simplejson, "loads", strdata, 1000)
calling:  loads  in  <module 'simplejson' from 'C:\\Users\\jophine.antony\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\site-packages\\simplejson\\__init__.py'>   1000  times
total time:  0:00:00.040890
{'1': 100, '2': 'acs', '3.5': 3.5567, 'd': [1, '23'], 'e': {'a': 'A'}}

Per le versioni:

  • python: 3.7.4
  • json: 2.0.9
  • simplejson: 3.17.0

json era più veloce di simplejson durante l'operazione di scarico ma entrambi mantenevano la stessa velocità durante le operazioni di carico


0

Mi sono imbattuto in questa domanda mentre cercavo di installare simplejson per Python 2.6. Avevo bisogno di usare 'object_pairs_hook' di json.load () per caricare un file json come OrderedDict. Avendo familiarità con le versioni più recenti di Python non mi sono reso conto che il modulo json per Python 2.6 non include "object_pairs_hook", quindi ho dovuto installare simplejson per questo scopo. Per esperienza personale, questo è il motivo per cui utilizzo simplejson al contrario del modulo json standard.

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.