Was sind die Unterschiede zwischen json- und simplejson-Python-Modulen?

381

Ich habe viele Projekte gesehen, die simplejsonModule anstelle von jsonModulen aus der Standardbibliothek verwenden. Es gibt auch viele verschiedene simplejsonModule. Warum sollten diese Alternativen anstelle der in der Standardbibliothek verwendet werden?

Lakshman Prasad
quelle

Antworten:

391

json wird simplejson zur stdlib hinzugefügt. Aber da jsonin 2.6 hinzugefügt wurde, simplejsonhat der Vorteil, an mehr Python-Versionen (2.4+) zu arbeiten.

simplejsonwird auch häufiger aktualisiert als Python. Wenn Sie also die neueste Version benötigen (oder möchten), verwenden Sie diese nach Möglichkeit am besten simplejsonselbst.

Eine gute Praxis ist meiner Meinung nach, das eine oder andere als Fallback zu verwenden.

try:
    import simplejson as json
except ImportError:
    import json
Devin Jeanpierre
quelle
2
Wenn ich nur Pyflakes dazu bringen könnte, mich nicht mehr zu beschwerenredefinition of unused 'json'
James McMahon,
5
Sie sind weder gleich noch kompatibel, simplejson hat einen JSONDecodeError und json hat einen ValueError
Björn
3
@BjornTipling JSONDecodeErrorist eine Unterklasse vonValueError
elhefe
30
Ich bin mit der obigen Antwort nicht einverstanden, vorausgesetzt, Sie haben ein aktuelles Python. Die integrierte (großartiges Plus !!!) Json-Bibliothek in Python 2.7 ist so schnell wie simplejson und weist weniger Unicode-Fehler auf, die nicht behoben werden können. Siehe Antwort stackoverflow.com/a/16131316/78234
Tal Weiss
1
Es scheint, dass Python2.7 json simplejson v2.0.9 übernommen hat, was zum Zeitpunkt des Schreibens weit hinter dem aktuellen simplejson v3.6.5 zurückliegt. Es gibt viele Verbesserungen, die den Import wert sind. Simplejson
Kenji Noguchi
82

Ich muss den anderen Antworten nicht zustimmen: Die eingebaute jsonBibliothek (in Python 2.7) ist nicht unbedingt langsamer als simplejson. Es hat auch nicht diesen nervigen Unicode-Fehler .

Hier ist ein einfacher 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)

Und die Ergebnisse auf meinem System (Python 2.7.4, Linux 64-Bit):

Komplexe Daten aus der realen Welt:
JSON-Dumps 1,56666707993 Sekunden
simplejson-Dumps 2,25638604164 Sekunden
json lädt 2,71256899834 Sekunden
simplejson lädt 1,29233884811 Sekunden

Einfache Daten:
JSON-Dumps 0,370109081268 Sekunden
simplejson-Dumps 0,574181079865 Sekunden
json lädt 0,422876119614 Sekunden
simplejson lädt 0,270955085754 Sekunden

Zum Dumping jsonist schneller als simplejson. Zum Laden geht simplejsones schneller.

Da ich gerade einen Webdienst aufbaue, dumps()ist dies wichtiger - und die Verwendung einer Standardbibliothek wird immer bevorzugt.

Auch cjsonwurde in den letzten 4 Jahren nicht aktualisiert, so dass ich es nicht anfassen würde.

Tal Weiss
quelle
Das ist irreführend. Meine Antwort unten erklärt warum.
notbad.jpeg
2
Auf meinem Win7-PC (i7-CPU) ist json(CPython 3.5.0) bei einfachen | komplexen Speicherauszügen 68% | 45% schneller und bei einfachen | komplexen Ladevorgängen ab Version simplejson3.8.0 mit C-Beschleunigungen unter Verwendung Ihres Benchmark-Codes 35% | 17% schneller . Daher würde ich simplejson mit diesem Setup nicht mehr verwenden.
Mab
1
Ich habe dies gerade auf Python 3.6.1 ausgeführt und jsongewinnt oder ist für alle Tests gleich. In der Tat jsonist etwas weniger als doppelt so schnell wie der komplexe Real-World-Data-Dumps-Test!
CpILL
27

Alle diese Antworten sind nicht sehr hilfreich, da sie zeitkritisch sind .

Nachdem ich einige Nachforschungen angestellt hatte, stellte ich fest, dass dies simplejsontatsächlich schneller ist als das eingebaute, wenn Sie es auf die neueste Version aktualisieren.

pip/easy_installwollte 2.3.2 auf Ubuntu 12.04 installieren, aber nachdem ich herausgefunden hatte, dass die neueste simplejsonVersion tatsächlich 3.3.0 ist, habe ich sie aktualisiert und die Zeittests erneut durchgeführt.

  • simplejsonist etwa 3x schneller als das eingebaute jsonbei Lasten
  • simplejsonist etwa 30% schneller als das eingebaute jsonauf Müllkippen

Haftungsausschluss:

Die obigen Anweisungen sind in Python-2.7.3 und simplejson 3.3.0 (mit c-Beschleunigungen) enthalten. Um sicherzustellen, dass meine Antwort auch nicht zeitkritisch ist, sollten Sie Ihre eigenen Tests durchführen , um dies zu überprüfen, da sie zwischen den Versionen sehr unterschiedlich sind. Es gibt keine einfache Antwort, die nicht zeitkritisch ist.

So erkennen Sie, ob C-Beschleunigungen in simplejson aktiviert sind:

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

UPDATE: Ich bin kürzlich auf eine Bibliothek namens ujson gestoßen , die ~ 3x schneller arbeitet als simplejsoneinige grundlegende Tests.

notbad.jpeg
quelle
Danke, dass du Ujson erwähnt hast. Dieser führte mich zu einer anderen Bibliothek RapidJSON, die besser gepflegt aussieht
MCMZL
"simplejson 3.3.0 (mit c speedups)" oh wirklich? Seien Sie ehrlicher und testen Sie es ohne Beschleunigung.
Reishin
Verwenden Sie Ujson nicht, es ist übersät mit Fehlern und Speicherlecks und Crashern und wurde seit einiger Zeit nicht mehr aktualisiert. Wir haben es fallen lassen und auf simplejson umgestellt, da es mehr Funktionen als json hat und aktualisiert wird
amohr
21

Ich habe json, simplejson und cjson verglichen.

  • cjson ist am schnellsten
  • simplejson ist fast auf Augenhöhe mit cjson
  • json ist ungefähr 10x langsamer als 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
Chris
quelle
6
Bitte fügen Sie eine Pastete für das eigentliche Testmodul hinzu.
Tal Weiss
4
Welche Versionen von Python und den fraglichen Bibliotheken?
Anentropic
6
Das stimmt nicht mehr. json in python2.7 ist eine Leistungsverbesserung.
Zengr
11

Einige Werte werden zwischen simplejson und json unterschiedlich serialisiert.

Insbesondere werden Instanzen von collections.namedtupleals Arrays von, jsonaber als Objekte von serialisiert simplejson. Sie können dieses Verhalten überschreiben namedtuple_as_object=False, indem Sie an übergeben simplejson.dump, aber standardmäßig stimmen die Verhaltensweisen nicht überein.

>>> 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]'
pfhayes
quelle
7

Eine API-Inkompatibilität, die ich mit Python 2.7 gegenüber simplejson 3.3.1 gefunden habe, besteht darin, ob die Ausgabe str- oder unicode-Objekte erzeugt. z.B

>>> 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'}

Wenn die Verwendung von simplejson bevorzugt wird, kann dies behoben werden, indem die Argumentzeichenfolge wie in: Unicode erzwungen wird:

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

Der Zwang erfordert die Kenntnis des ursprünglichen Zeichensatzes, zum Beispiel:

>>> 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)

Dies ist das Problem 40, das nicht behoben werden kann

jjc
quelle
6

Ein weiterer Grund, warum Projekte simplejson verwenden, ist, dass der eingebaute json ursprünglich keine C-Beschleunigungen enthielt, sodass der Leistungsunterschied spürbar war.

A. Coady
quelle
5

Das eingebaute jsonModul wurde in Python 2.6 aufgenommen. Alle Projekte, die Versionen von Python <2.6 unterstützen, müssen einen Fallback haben. In vielen Fällen ist dies ein Fallback simplejson.

thedz
quelle
4

Hier ist ein (inzwischen veralteter) Vergleich der Python-JSON-Bibliotheken:

Vergleichen von JSON-Modulen für Python ( Archivlink )

Unabhängig von den Ergebnissen in diesem Vergleich sollten Sie die Standardbibliothek json verwenden, wenn Sie mit Python 2.6 arbeiten. Und ... könnte genauso gut einfach simplejson verwenden.

Van Gale
quelle
2

Das simplejson-Modul ist einfach 1,5-mal schneller als json (auf meinem Computer mit simplejson 2.1.1 und Python 2.7 x86).

Wenn Sie möchten, können Sie den Benchmark ausprobieren: http://abral.altervista.org/jsonpickle-bench.zip Auf meinem PC ist simplejson schneller als cPickle. Ich würde gerne auch Ihre Benchmarks kennen!

Wie Coady sagte, besteht der Unterschied zwischen simplejson und json wahrscheinlich darin, dass simplejson _speedups.c enthält. Warum verwenden Python-Entwickler nicht simplejson?

Jeko
quelle
2

In python3, wenn Sie eine Reihe von b'bytes', mit jsonIhnen zu haben , .decode()den Inhalt , bevor Sie es laden. simplejsonkümmert sich darum, damit Sie es einfach tun können simplejson.loads(byte_string).

voidnologo
quelle
In Version 3.6 geändert: s kann jetzt vom Typ Bytes oder Bytearray sein. Die Eingabecodierung sollte UTF-8, UTF-16 oder UTF-32 sein.
Mathieu Longtin
1

jsonscheint schneller als simplejsonin beiden Fällen von Ladevorgängen und Dumps in der neuesten Version

Getestete Versionen:

  • Python: 3.6.8
  • json: 2.0.9
  • simplejson: 3.16.0

Ergebnisse:

>>> 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'}}

Für Versionen:

  • Python: 3.7.4
  • json: 2.0.9
  • simplejson: 3.17.0

json war während des Dump-Betriebs schneller als simplejson, aber beide behielten während des Ladevorgangs die gleiche Geschwindigkeit bei

jophine
quelle
0

Ich bin auf diese Frage gestoßen, als ich simplejson für Python 2.6 installieren wollte. Ich musste den 'object_pairs_hook' von json.load () verwenden, um eine json-Datei als OrderedDict zu laden. Da ich mit neueren Versionen von Python vertraut war, wusste ich nicht, dass das json-Modul für Python 2.6 nicht den 'object_pairs_hook' enthält, daher musste ich simplejson für diesen Zweck installieren. Aus persönlicher Erfahrung verwende ich deshalb simplejson im Gegensatz zum Standard-json-Modul.

BeeLabeille
quelle