Jakie są różnice między modułami json i simplejson Python?

381

Widziałem wiele projektów wykorzystujących simplejsonmoduł zamiast jsonmodułu ze standardowej biblioteki. Istnieje również wiele różnych simplejsonmodułów. Dlaczego warto korzystać z tych alternatyw zamiast w Bibliotece standardowej?

Lakshman Prasad
źródło

Odpowiedzi:

391

json jest simplejson dodawany do stdlib. Ale ponieważ jsonzostał dodany w wersji 2.6, simplejsonma tę zaletę, że działa na większej liczbie wersji Pythona (2.4+).

simplejsonjest również aktualizowany częściej niż Python, więc jeśli potrzebujesz (lub chcesz) najnowszej wersji, najlepiej użyć jej simplejson, jeśli to możliwe.

Moim zdaniem dobrą praktyką jest używanie jednego lub drugiego jako rezerwowego.

try:
    import simplejson as json
except ImportError:
    import json
Devin Jeanpierre
źródło
2
Teraz, gdybym tylko mógł uzyskać płatki pyłu, żeby przestać narzekaćredefinition of unused 'json'
James McMahon,
5
Nie są takie same ani kompatybilne, simplejson ma JSONDecodeError, a json ma ValueError
Bjorn
3
@BjornTipling JSONDecodeErrorjest podklasąValueError
elhefe 16.04.13
30
Nie zgadzam się z powyższą odpowiedzią, zakładając, że masz aktualny Python. Wbudowana (świetna plus !!!) biblioteka Json w Pythonie 2.7 jest tak szybka jak simplejson i ma mniej błędów, które nie zostały naprawione w Unicode. Zobacz odpowiedź stackoverflow.com/a/16131316/78234
Tal Weiss
1
Wygląda na to, że json Python2.7 przyjął simplejson v2.0.9, co jest daleko w tyle za obecnym simplejson v3.6.5 w chwili pisania. Istnieje wiele ulepszeń wartych importu simplejson
Kenji Noguchi
82

Muszę się nie zgadzać z innymi odpowiedziami: wbudowana jsonbiblioteka (w Pythonie 2.7) niekoniecznie jest wolniejsza niż simplejson. Nie ma też tego irytującego błędu unicode .

Oto prosty punkt odniesienia:

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)

A wyniki w moim systemie (Python 2.7.4, Linux 64-bit):

Złożone dane ze świata rzeczywistego:
zrzuty Jsona 1,56666707993 sekundy
zrzuty simplejsona 2,26638604164 sekundy
załadowania Jsona 2,71256899834 sekundy
załadowania simplejson 1.29233884811 sekund

Proste dane:
zrzuty jsona 0,370109081268 sekund
zrzuty simplejsona 0,574181079865 sekundy
załadowania jsona 0,422876119614 sekundy
załadowania simplejsona 0,270955085754 sekundy

Do dumpingu jsonjest szybszy niż simplejson. Do ładowania simplejsonjest szybszy.

Ponieważ obecnie buduję usługę internetową, dumps()jest to ważniejsze - i zawsze preferowana jest standardowa biblioteka.

Ponadto cjsonnie był aktualizowany w ciągu ostatnich 4 lat, więc nie chciałbym go dotykać.

Tal Weiss
źródło
To jest mylące. Moja odpowiedź poniżej wyjaśnia, dlaczego.
notbad.jpeg
2
Na moim Win7 PC (i7 CPU) json(CPython 3.5.0) jest o 68% | 45% szybszy przy prostych | złożonych zrzutach i 35% | 17% przy prostych | złożonych ładowaniach wrt w wersji simplejson3.0.0 z przyspieszeniami C przy użyciu kodu testu porównawczego. Dlatego nie używałbym już simplejson w tej konfiguracji.
mab
1
Właśnie uruchomiłem to w Pythonie 3.6.1 i jsonwygrywa lub jest taki sam dla wszystkich testów. W rzeczywistości jsonjest nieco mniej niż dwa razy szybszy od złożonego testu zrzutów danych w świecie rzeczywistym!
CpILL
27

Wszystkie te odpowiedzi nie są zbyt pomocne, ponieważ są wrażliwe na czas .

Po przeprowadzeniu własnych badań odkryłem, że simplejsonjest on rzeczywiście szybszy niż wbudowane, jeśli będziesz go aktualizować do najnowszej wersji.

pip/easy_installChciałem zainstalować 2.3.2 na Ubuntu 12.04, ale po odkryciu, że najnowsza simplejsonwersja jest w rzeczywistości 3.3.0, zaktualizowałem ją i ponownie przeprowadziłem testy czasowe.

  • simplejson jest około 3 razy szybszy niż wbudowany json przy obciążeniach
  • simplejsonjest około 30% szybszy niż wbudowany jsonw zrzutach

Zrzeczenie się:

Powyższe instrukcje znajdują się w python-2.7.3 i simplejson 3.3.0 (z przyspieszeniami c) I aby upewnić się, że moja odpowiedź również nie jest wrażliwa na czas, powinieneś uruchomić własne testy, aby sprawdzić, ponieważ różnią się one bardzo między wersjami; nie ma łatwej odpowiedzi, która nie byłaby wrażliwa na czas.

Jak stwierdzić, czy przyspieszenia C są włączone w simplejson:

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

AKTUALIZACJA: Ostatnio natknąłem się na bibliotekę o nazwie ujson, która działa ~ 3 razy szybciej niż w simplejsonprzypadku niektórych podstawowych testów.

notbad.jpeg
źródło
Dzięki za wspomnienie ujsona. Ten doprowadził mnie do innej biblioteki RapidJSON, która wygląda lepiej utrzymana
MCMZL
„simplejson 3.3.0 (z przyspieszeniami c)” och, naprawdę? bądź bardziej uczciwy i przetestuj go bez przyspieszeń C.
Reishin
nie używaj ujsona, jest on pełen błędów, wycieków pamięci i awarii oraz nie był aktualizowany od dłuższego czasu. Porzuciliśmy go i przełączyliśmy na simplejson, ponieważ ma więcej funkcji niż json i jest aktualizowany
amohr
21

Porównywałem testy Json, Simplejson i CJson.

  • cjson jest najszybszy
  • simplejson jest prawie na równi z cjson
  • json jest około 10 razy wolniejszy niż 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
źródło
6
Dodaj ciasto do rzeczywistego modułu testowego.
Tal Weiss
4
które wersje Pythona i omawiane biblioteki?
Anentropic
6
To już nie jest prawda. json w python2.7 to ulepszenia wydajności.
zengr
11

Niektóre wartości są serializowane w różny sposób między simplejson i json.

W szczególności wystąpienia collections.namedtuplesą szeregowane jako tablice według, jsonale jako obiekty według simplejson. Możesz zmienić to zachowanie, przechodząc namedtuple_as_object=Falsedo simplejson.dump, ale domyślnie zachowania się nie zgadzają.

>>> 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
źródło
7

Zgodność API, którą znalazłem w Pythonie 2.7 w porównaniu z simplejson 3.3.1 dotyczy tego, czy dane wyjściowe tworzą obiekty str, czy Unicode. na przykład

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

Jeśli preferowane jest użycie simplejson, można temu zaradzić, zmuszając ciąg argumentu do Unicode, jak w:

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

Przymus wymaga znajomości oryginalnego zestawu znaków, na przykład:

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

To nie naprawi problemu 40

jjc
źródło
6

Innym powodem, dla którego projekty wykorzystują simplejson, jest to, że wbudowany json pierwotnie nie zawierał swoich przyspieszeń C, więc różnica w wydajności była zauważalna.

A. Coady
źródło
5

Wbudowany jsonmoduł został włączony do Pythona 2.6. Wszystkie projekty, które obsługują wersje Pythona <2.6, muszą mieć awarię. W wielu przypadkach jest to awaria simplejson.

thedz
źródło
4

Oto (obecnie nieaktualne) porównanie bibliotek Python Json:

Porównanie modułów JSON dla Pythona ( link do archiwum )

Niezależnie od wyników w tym porównaniu, powinieneś używać standardowej biblioteki json, jeśli korzystasz z Pythona 2.6. I .. równie dobrze może po prostu użyć simplejson inaczej.

Van Gale
źródło
2

Moduł simplejson jest po prostu 1,5 razy szybszy niż json (na moim komputerze z simplejson 2.1.1 i Python 2.7 x86).

Jeśli chcesz, możesz wypróbować test: http://abral.altervista.org/jsonpickle-bench.zip Na moim komputerze simplejson jest szybszy niż cPickle. Chciałbym poznać również twoje punkty odniesienia!

Prawdopodobnie, jak powiedział Coady, różnica między simplejson i json polega na tym, że simplejson obejmuje _speedups.c. Dlaczego więc programiści python nie używają simplejson?

Jeko
źródło
2

W python3, jeśli masz ciąg znaków b'bytes', jsonmusisz mieć .decode()zawartość, zanim będziesz mógł ją załadować. simplejsonzajmuje się tym, więc możesz po prostu to zrobić simplejson.loads(byte_string).

voidnologo
źródło
Zmieniono w wersji 3.6: s mogą być teraz typu bajt lub tablica bajtowa. Kodowanie wejściowe powinno być UTF-8, UTF-16 lub UTF-32.
Mathieu Longtin
1

json wydaje się szybszy niż simplejson w obu przypadkach obciążeń i zrzutów w najnowszej wersji

Testowane wersje:

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

Wyniki:

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

Dla wersji:

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

json był szybszy niż simplejson podczas operacji zrzutu, ale oba utrzymywały tę samą prędkość podczas operacji ładowania

jofine
źródło
0

Natknąłem się na to pytanie, gdy chciałem zainstalować simplejson dla Pythona 2.6. Musiałem użyć „object_pairs_hook” z json.load (), aby załadować plik json jako OrDERDict. Znając nowsze wersje Pythona, nie zdawałem sobie sprawy, że moduł json dla Pythona 2.6 nie zawiera „haka_obiektu_obiektu”, dlatego w tym celu musiałem zainstalować simplejson. Z własnego doświadczenia dlatego używam simplejson w przeciwieństwie do standardowego modułu json.

BeeLabeille
źródło