Widziałem wiele projektów wykorzystujących simplejson
moduł zamiast json
modułu ze standardowej biblioteki. Istnieje również wiele różnych simplejson
modułów. Dlaczego warto korzystać z tych alternatyw zamiast w Bibliotece standardowej?
Widziałem wiele projektów wykorzystujących simplejson
moduł zamiast json
modułu ze standardowej biblioteki. Istnieje również wiele różnych simplejson
modułów. Dlaczego warto korzystać z tych alternatyw zamiast w Bibliotece standardowej?
Odpowiedzi:
json
jest simplejson
dodawany do stdlib. Ale ponieważ json
został dodany w wersji 2.6, simplejson
ma tę zaletę, że działa na większej liczbie wersji Pythona (2.4+).
simplejson
jest 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
JSONDecodeError
jest podklasąValueError
Muszę się nie zgadzać z innymi odpowiedziami: wbudowana json
biblioteka (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 sekundProste 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 json
jest szybszy niż simplejson
. Do ładowania simplejson
jest szybszy.
Ponieważ obecnie buduję usługę internetową, dumps()
jest to ważniejsze - i zawsze preferowana jest standardowa biblioteka.
Ponadto cjson
nie był aktualizowany w ciągu ostatnich 4 lat, więc nie chciałbym go dotykać.
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 simplejson
3.0.0 z przyspieszeniami C przy użyciu kodu testu porównawczego. Dlatego nie używałbym już simplejson w tej konfiguracji.
json
wygrywa lub jest taki sam dla wszystkich testów. W rzeczywistości json
jest nieco mniej niż dwa razy szybszy od złożonego testu zrzutów danych w świecie rzeczywistym!
Wszystkie te odpowiedzi nie są zbyt pomocne, ponieważ są wrażliwe na czas .
Po przeprowadzeniu własnych badań odkryłem, że simplejson
jest on rzeczywiście szybszy niż wbudowane, jeśli będziesz go aktualizować do najnowszej wersji.
pip/easy_install
Chciałem zainstalować 2.3.2 na Ubuntu 12.04, ale po odkryciu, że najnowsza simplejson
wersja 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ążeniachsimplejson
jest około 30% szybszy niż wbudowany json
w zrzutachPowyż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.
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 simplejson
przypadku niektórych podstawowych testów.
Porównywałem testy Json, Simplejson i CJson.
$ 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
Niektóre wartości są serializowane w różny sposób między simplejson i json.
W szczególności wystąpienia collections.namedtuple
są szeregowane jako tablice według, json
ale jako obiekty według simplejson
. Możesz zmienić to zachowanie, przechodząc namedtuple_as_object=False
do 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]'
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
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.
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?
W python3, jeśli masz ciąg znaków b'bytes'
, json
musisz mieć .decode()
zawartość, zanim będziesz mógł ją załadować. simplejson
zajmuje się tym, więc możesz po prostu to zrobić simplejson.loads(byte_string)
.
json
wydaje się szybszy niż simplejson
w obu przypadkach obciążeń i zrzutów w najnowszej wersji
Testowane wersje:
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:
json był szybszy niż simplejson podczas operacji zrzutu, ale oba utrzymywały tę samą prędkość podczas operacji ładowania
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.
redefinition of unused 'json'