J'ai vu de nombreux projets utilisant le module simplejson
au lieu du module json
du Bibliothèque standard. En outre, il existe de nombreux modules simplejson
. Pourquoi utiliser ces alternatives au lieu de celles de la bibliothèque standard?
json
estsimplejson
, ajouté à la bibliothèque standard. Mais depuis que json
a été ajouté dans la version 2.6, simplejson
a l’avantage de travailler sur plusieurs versions de Python (2.4+).
simplejson
est également mis à jour plus fréquemment que Python. Par conséquent, si vous avez besoin (ou souhaitez) de la version la plus récente, il est préférable d'utiliser simplejson
lui-même, si possible.
À mon avis, une bonne pratique consiste à utiliser l’une ou l’autre comme solution de rechange.
try:
import simplejson as json
except ImportError:
import json
Je ne suis pas d'accord avec les autres réponses: la bibliothèque intégrée json
(dans Python 2.7) n'est pas nécessairement plus lente que simplejson
. Il n'a pas non plus ce bogue unicode ennuyeux .
Voici un repère simple:
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)
Et les résultats sur mon système (Python 2.7.4, Linux 64 bits):
Données du monde réel complexes:
Json affiche 1,56666707993 secondes
simplejson vidages 2,25638604164 secondes
json charge 2.71256899834 secondes
simplejson charge 1.29233884811 secondesDonnées simples:
json dumps 0.370109081268 secondes
simplejson dumps 0.574181079865 secondes
json charge 0.422876119614 secondes
simplejson charge en 0.270955085754 secondes
Pour le dumping, json
est plus rapide que simplejson
. Pour le chargement, simplejson
est plus rapide.
Étant donné que je construis actuellement un service Web, dumps()
est plus important et l'utilisation d'une bibliothèque standard est toujours préférable.
De plus, cjson
n'a pas été mis à jour au cours des 4 dernières années, je ne le toucherais donc pas.
Toutes ces réponses ne sont pas très utiles car elles sont sensibles au temps .
Après avoir effectué mes propres recherches, j’ai trouvé que simplejson
est en effet plus rapide que l’intégré si vous le mettez à jour avec la dernière version.
pip/easy_install
voulait installer la version 2.3.2 sur Ubuntu 12.04, mais après avoir découvert la dernière version de simplejson
est en fait la version 3.3.0, je l'ai donc mise à jour et j'ai relancé les tests de temps.
simplejson
est environ 3 fois plus rapide que la fonction intégrée json
à des chargessimplejson
est environ 30% plus rapide que la fonction intégrée json
aux déchargesLes instructions ci-dessus sont en python-2.7.3 et simplejson 3.3.0 (avec c accélérations). Et pour être sûr que ma réponse n’est pas sensible au temps, vous devez exécuter vos propres tests à vérifier car cela varie beaucoup d'une version à l'autre; il n'y a pas de réponse facile qui ne soit pas sensible au temps.
import simplejson
# If this is True, then c speedups are enabled.
print bool(getattr(simplejson, '_speedups', False))
UPDATE: Je suis récemment tombé sur une bibliothèque appelée json qui exécute ~ 3x plus vite que simplejson
avec quelques bases tests.
J'ai comparé json, simplejson et 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
Certaines valeurs sont sérialisées différemment entre simplejson et json.
Notamment, les instances de collections.namedtuple
sont sérialisées en tant que tableaux par json
mais en tant qu'objets par simplejson
. Vous pouvez remplacer ce comportement en passant namedtuple_as_object=False
à simplejson.dump
, mais par défaut, les comportements ne correspondent pas.
>>> 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]'
Une incompatibilité d'API que j'ai trouvée, avec Python 2.7 vs simplejson 3.3.1 indique si la sortie génère des objets str ou unicode. par exemple.
>>> from json import JSONDecoder
>>> jd = JSONDecoder()
>>> jd.decode("""{ "a":"b" }""")
{u'a': u'b'}
contre
>>> from simplejson import JSONDecoder
>>> jd = JSONDecoder()
>>> jd.decode("""{ "a":"b" }""")
{'a': 'b'}
Si vous préférez utiliser simplejson, vous pouvez résoudre ce problème en contraignant l'argument à unicode, comme dans l'exemple suivant:
>>> from simplejson import JSONDecoder
>>> jd = JSONDecoder()
>>> jd.decode(unicode("""{ "a":"b" }""", "utf-8"))
{u'a': u'b'}
La coercition nécessite de connaître le jeu de caractères d'origine, par exemple:
>>> 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)
C'est la solution qui ne va pas numéro 4
Le module intégré json
a été inclus dans Python 2.6. Tous les projets qui prennent en charge les versions de Python <2.6 doivent avoir un repli. Dans de nombreux cas, ce repli est simplejson
.
Une autre raison pour laquelle les projets utilisent simplejson est que le JSON intégré n’incluait pas à l’origine les accélérations C, la différence de performances était donc perceptible.
Voici une comparaison (maintenant obsolète) des bibliothèques Python json:
Comparaison des modules JSON pour Python ( lien d'archive )
Quels que soient les résultats de cette comparaison, vous devez utiliser la bibliothèque standard json si vous êtes sur Python 2.6. Et .. pourrait aussi bien utiliser simplejson autrement.
En python3, si vous utilisez une chaîne de b'bytes'
, avec json
, vous devez .decode()
le contenu avant de pouvoir le charger. simplejson
prend soin de cela pour que vous puissiez simplement faire simplejson.loads(byte_string)
.
le module simplejson est tout simplement 1,5 fois plus rapide que json (sur mon ordinateur, avec simplejson 2.1.1 et Python 2,7 x86).
Si vous le souhaitez, vous pouvez essayer le repère: http://abral.altervista.org/jsonpickle-bench.Zip Sur mon PC, simplejson est plus rapide que cPickle. J'aimerais aussi connaître vos repères!
Probablement, comme dit Coady, la différence entre simplejson et json est que simplejson inclut _speedups.c. Alors, pourquoi les développeurs python n'utilisent-ils pas simplejson?
Je suis tombé sur cette question alors que je cherchais à installer simplejson pour Python 2.6. J'avais besoin d'utiliser le 'object_pairs_hook' de json.load () afin de charger un fichier json en tant que OrderedDict. Connaissant bien les versions plus récentes de Python, je ne savais pas que le module json pour Python 2.6 n'incluait pas 'object_pairs_hook'. J'ai donc dû installer simplejson à cette fin. De par mon expérience personnelle, c’est la raison pour laquelle j’utilise simplejson par opposition au module JSON standard.