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?
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?
Odpowiedzi:
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
JSONDecodeErrorjest podklasąValueError
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 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 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ć.
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.
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!
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ążeniachsimplejsonjest około 30% szybszy niż wbudowany jsonw 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 simplejsonprzypadku 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.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]'
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', 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).
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'