Quelles sont les différences entre les modules Python json et simplejson?

381

J'ai vu de nombreux projets utilisant le simplejsonmodule au lieu du jsonmodule de la bibliothèque standard. En outre, il existe de nombreux simplejsonmodules différents . Pourquoi utiliser ces alternatives au lieu de celle de la bibliothèque standard?

Lakshman Prasad
la source

Réponses:

391

json est simplejson ajouté à stdlib. Mais depuis qu'il a jsonété ajouté en 2.6, il simplejsona l'avantage de travailler sur plus de versions Python (2.4+).

simplejsonest également mis à jour plus fréquemment que Python, donc si vous avez besoin (ou souhaitez) la dernière version, il est préférable de s'utiliser simplejsonlui-même, si possible.

Une bonne pratique, à mon avis, consiste à utiliser l'un ou l'autre comme solution de rechange.

try:
    import simplejson as json
except ImportError:
    import json
Devin Jeanpierre
la source
2
Maintenant, si je pouvais seulement empêcher les pyflakes de se plaindreredefinition of unused 'json'
James McMahon
5
Ils ne sont pas identiques ni compatibles, simplejson a un JSONDecodeError et json a un ValueError
Bjorn
3
@BjornTipling JSONDecodeErrorest une sous-classe deValueError
elhefe
30
Je ne suis pas d'accord avec la réponse ci-dessus en supposant que vous disposez d'un Python à jour. La bibliothèque Json intégrée (super plus !!!) en Python 2.7 est aussi rapide que simplejson et a moins de bogues Unicode refusés d'être corrigés. Voir la réponse stackoverflow.com/a/16131316/78234
Tal Weiss
1
Il semble que Python2.7 json ait adopté simplejson v2.0.9 qui est loin derrière le simplejson v3.6.5 actuel au moment de l'écriture. Il y a beaucoup d'améliorations qui valent l'importation simplejson
Kenji Noguchi
82

Je dois être en désaccord avec les autres réponses: la jsonbibliothèque intégrée (en Python 2.7) n'est pas nécessairement plus lente que simplejson. Il n'a pas non plus ce bug unicode ennuyeux .

Voici une référence 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 complexes du monde réel:
vidages json 1.56666707993 secondes
vidages simplejson 2.25638604164 secondes
charges json 2.71256899834 secondes
charges simplejson 1.29233884811 secondes

Données simples:
vidages json 0,370109081268 secondes
vidages simplejson 0,574181079865 secondes
charges json 0,422876119614 secondes
charges simplesjson 0,270955085754 secondes

Pour le dumping, jsonest plus rapide que simplejson. Pour le chargement, simplejsonc'est plus rapide.

Étant donné que je suis en train de créer un service Web, dumps()c'est plus important et l'utilisation d'une bibliothèque standard est toujours préférable.

De plus, cjsonn'a pas été mis à jour au cours des 4 dernières années, donc je n'y toucherais pas.

Tal Weiss
la source
C'est trompeur. Ma réponse ci-dessous explique pourquoi.
notbad.jpeg
2
Sur mon PC Win7 (CPU i7), json(CPython 3.5.0) est 68% | 45% plus rapide sur les vidages simples | complexes et 35% | 17% sur les charges simples | complexes par rapport à simplejsonv3.8.0 avec des accélérations C en utilisant votre code de référence. Par conséquent, je n'utiliserais plus simplejson avec cette configuration.
mab
1
Je viens de l'exécuter sur Python 3.6.1 et jsongagne ou est le même pour tous les tests. En fait, jsonc'est un peu moins de deux fois plus rapide que le test complexe de décharges de données du monde réel!
CpILL
27

Toutes ces réponses ne sont pas très utiles car elles sont sensibles au temps .

Après avoir fait mes propres recherches, j'ai trouvé que simplejsonc'était en effet plus rapide que le programme intégré, si vous le maintenez à jour avec la dernière version.

pip/easy_installsimplejsonJe voulais installer 2.3.2 sur Ubuntu 12.04, mais après avoir découvert que la dernière version est en fait la 3.3.0, je l'ai donc mise à jour et relancé les tests de temps.

  • simplejsonest environ 3 fois plus rapide que la fonction intégrée jsonà des charges
  • simplejsonest environ 30% plus rapide que la fonction intégrée jsondans les décharges

Avertissement:

Les énoncés ci - dessus sont en python-2.7.3 et 3.3.0 simplejson (avec c speedups) Et pour vous assurer que ma réponse n'est pas sensible au temps, vous devriez également exécuter vos propres tests pour vérifier car il varie tellement entre les versions; il n'y a pas de réponse facile qui ne soit pas sensible au temps.

Comment savoir si les accélérations C sont activées dans simplejson:

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

MISE À JOUR: J'ai récemment rencontré une bibliothèque appelée ujson qui fonctionne environ 3 fois plus rapidement simplejsonqu'avec certains tests de base.

notbad.jpeg
la source
Merci d'avoir mentionné ujson. Celui-ci m'a conduit à une autre bibliothèque RapidJSON qui a l'air mieux entretenue
MCMZL
"simplejson 3.3.0 (avec accélérations c)" oh vraiment? soyez plus honnête et testez-le sans accélérations c.
Reishin
n'utilisez pas ujson, il est jonché de bugs, de fuites de mémoire et de plantages et n'a pas été mis à jour depuis un certain temps. Nous l'avons abandonné et sommes passés à simplejson car il a plus de fonctionnalités que json et est mis à jour
amohr
21

J'ai comparé json, simplejson et cjson.

  • cjson est le plus rapide
  • simplejson est presque à égalité avec cjson
  • json est environ 10 fois plus lent que 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
la source
6
Veuillez ajouter un pastie pour le module de test réel.
Tal Weiss
4
quelles versions de Python et des bibliothèques en question?
Anentropic
6
Ce n'est plus vrai. json en python2.7 est une amélioration des performances.
zengr
11

Certaines valeurs sont sérialisées différemment entre simplejson et json.

Notamment, les instances de collections.namedtuplesont sérialisées en tant que tableaux par jsonmais 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]'
pfhayes
la source
7

Une incompatibilité d'API que j'ai trouvée avec Python 2.7 vs simplejson 3.3.1 est de savoir si la sortie produit 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 la préférence est d'utiliser simplejson, cela peut être résolu en contraignant la chaîne d'argument à unicode, comme dans:

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

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

Ceci ne résoudra pas le problème 40

jjc
la source
6

Une autre raison pour laquelle les projets utilisent simplejson est que le json intégré n'incluait pas à l'origine ses accélérations C, de sorte que la différence de performances était notable.

A. Coady
la source
5

Le jsonmodule intégré a été inclus dans Python 2.6. Tous les projets qui prennent en charge les versions de Python <2.6 doivent avoir une solution de secours. Dans de nombreux cas, cette solution de rechange est simplejson.

thedz
la source
4

Voici (une comparaison désormais obsolète) des bibliothèques json Python:

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 tout aussi bien utiliser simplejson autrement.

Van Gale
la source
2

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 la référence: 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 l'a dit Coady, la différence entre simplejson et json est que simplejson inclut _speedups.c. Alors, pourquoi les développeurs de python n'utilisent-ils pas simplejson?

Jeko
la source
2

En python3, si vous une chaîne de b'bytes', jsonvous devez avoir .decode()le contenu avant de pouvoir le charger. simplejsons'occupe de cela pour que vous puissiez le faire simplejson.loads(byte_string).

voidnologo
la source
Modifié dans la version 3.6: les s peuvent désormais être de type octets ou bytearray. Le codage d'entrée doit être UTF-8, UTF-16 ou UTF-32.
Mathieu Longtin
1

jsonsemble plus rapide que simplejsondans les deux cas de charges et de vidages dans la dernière version

Versions testées:

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

Résultats:

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

Pour les versions:

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

json était plus rapide que simplejson pendant le fonctionnement des décharges mais les deux ont maintenu la même vitesse pendant les opérations de chargement

jophine
la source
0

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 les versions plus récentes de Python, je ne savais pas que le module json pour Python 2.6 n'inclut pas le 'object_pairs_hook', j'ai donc dû installer simplejson à cet effet. Par expérience personnelle, c'est pourquoi j'utilise simplejson par opposition au module json standard.

BeeLabeille
la source