¿Cuáles son las diferencias entre los módulos Python json y simplejson?

381

He visto muchos proyectos usando el simplejsonmódulo en lugar del jsonmódulo de la Biblioteca Estándar. Además, hay muchos simplejsonmódulos diferentes . ¿Por qué usar estas alternativas, en lugar de la de la Biblioteca estándar?

Lakshman Prasad
fuente

Respuestas:

391

json es simplejson , agregado a stdlib. Pero como jsonse agregó en 2.6, simplejsontiene la ventaja de trabajar en más versiones de Python (2.4+).

simplejsontambién se actualiza con más frecuencia que Python, por lo que si necesita (o desea) la última versión, es mejor usarla simplejson, si es posible.

Una buena práctica, en mi opinión, es usar uno u otro como respaldo.

try:
    import simplejson as json
except ImportError:
    import json
Devin Jeanpierre
fuente
2
Ahora, si solo pudiera conseguir que los copos de nieve dejaran de quejarseredefinition of unused 'json'
James McMahon el
55
No son iguales ni compatibles, simplejson tiene un JSONDecodeError y json tiene un ValueError
Bjorn
3
@BjornTipling JSONDecodeErrores una subclase deValueError
elhefe
30
No estoy de acuerdo con la respuesta anterior, suponiendo que tenga un Python actualizado. La biblioteca Json incorporada (¡¡¡un gran plus !!!) en Python 2.7 es tan rápida como simplejson y tiene menos errores unicode denegados a ser reparados. Ver respuesta stackoverflow.com/a/16131316/78234
Tal Weiss
1
Parece que Python2.7 json adoptó simplejson v2.0.9, que está muy por detrás del actual simplejson v3.6.5 en el momento de la escritura. Hay muchas mejoras que vale la pena importar simplejson
Kenji Noguchi
82

Tengo que estar en desacuerdo con las otras respuestas: la jsonbiblioteca integrada (en Python 2.7) no es necesariamente más lenta que simplejson. Tampoco tiene este molesto error Unicode .

Aquí hay un punto de referencia 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)

Y los resultados en mi sistema (Python 2.7.4, Linux 64-bit):

Datos complejos del mundo real:
json vuelca 1.56666707993 segundos
simplejson vuelca 2.25638604164 segundos
json carga 2.71256899834 segundos
simplejson carga 1.29233884811 segundos

Datos simples:
json vuelca 0.370109081268 segundos
simplejson vuelca 0.574181079865 segundos
json carga 0.422876119614 segundos
simplejson carga 0.270955085754 segundos

Para el dumping, jsones más rápido que simplejson. Para cargar, simplejsones más rápido.

Dado que actualmente estoy creando un servicio web, dumps()es más importante, y siempre se prefiere usar una biblioteca estándar.

Además, cjsonno se actualizó en los últimos 4 años, por lo que no lo tocaría.

Tal Weiss
fuente
Esto es engañoso. Mi respuesta a continuación explica por qué.
notbad.jpeg
2
En mi PC Win7 (CPU i7), json(CPython 3.5.0) es 68% | 45% más rápido en volcados simples | complejos y 35% | 17% en cargas simples | complejas wrt simplejsonv3.8.0 con aceleraciones en C usando su código de referencia. Por lo tanto, ya no usaría simplejson con esta configuración.
mab
1
Acabo de ejecutar esto en Python 3.6.1 y jsongana o es lo mismo para todas las pruebas. De hecho, ¡ jsones un poco menos del doble de rápido que la compleja prueba de volcado de datos del mundo real!
CpILL
27

Todas estas respuestas no son muy útiles porque son sensibles al tiempo .

Después de investigar un poco por mi cuenta, descubrí que simplejsones más rápido que el incorporado, si lo mantiene actualizado a la última versión.

pip/easy_installquería instalar 2.3.2 en ubuntu 12.04, pero después de descubrir que la última simplejsonversión es en realidad 3.3.0, lo actualicé y volví a probar las pruebas de tiempo.

  • simplejsones aproximadamente 3 veces más rápido que el incorporado jsonen las cargas
  • simplejsones aproximadamente un 30% más rápido que el incorporado jsonen los vertederos

Descargo de responsabilidad:

Las declaraciones anteriores están en python-2.7.3 y simplejson 3.3.0 (con aceleraciones c) Y para asegurarse de que mi respuesta tampoco sea sensible al tiempo, debe ejecutar sus propias pruebas para verificar, ya que varía mucho entre versiones; No hay una respuesta fácil que no sea sensible al tiempo.

Cómo saber si las aceleraciones de C están habilitadas en simplejson:

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

ACTUALIZACIÓN: Recientemente me encontré con una biblioteca llamada ujson que funciona ~ 3 veces más rápido que simplejsoncon algunas pruebas básicas.

notbad.jpeg
fuente
Gracias por mencionar a Ujson. Este me llevó a otra biblioteca RapidJSON que se ve mejor mantenida
MCMZL
"simplejson 3.3.0 (con aceleraciones c)" oh, ¿en serio? Sé más honesto y pruébalo sin c aceleraciones.
Reishin
no use ujson, está lleno de errores y pérdidas de memoria y bloqueadores, y no se ha actualizado en bastante tiempo. Lo abandonamos y cambiamos a simplejson, ya que tiene más funcionalidad que json y se actualiza
amohr
21

He estado comparando json, simplejson y cjson.

  • cjson es el más rápido
  • simplejson está casi a la par con cjson
  • json es aproximadamente 10 veces más lento 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
fuente
66
Agregue una empanada para el módulo de prueba real.
Tal Weiss
44
¿Qué versiones de Python y las bibliotecas en cuestión?
Anentropic
66
Esto ya no es verdad. json en python2.7 es mejoras de rendimiento.
zengr
11

Algunos valores se serializan de manera diferente entre simplejson y json.

En particular, las instancias de collections.namedtuplese serializan como matrices por jsonpero como objetos por simplejson. Puede anular este comportamiento pasando namedtuple_as_object=Falsea simplejson.dump, pero de forma predeterminada los comportamientos no coinciden.

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

Una incompatibilidad API que encontré, con Python 2.7 vs simplejson 3.3.1 está en si la salida produce objetos str o unicode. p.ej

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

Si la preferencia es usar simplejson, entonces esto puede abordarse coaccionando la cadena de argumento a unicode, como en:

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

La coerción requiere conocer el juego de caracteres original, por ejemplo:

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

Este es el problema no soluciona 40

jjc
fuente
6

Otra razón por la que los proyectos usan simplejson es que el json incorporado originalmente no incluía sus aceleraciones en C, por lo que la diferencia de rendimiento fue notable.

A. coadyuvante
fuente
5

El jsonmódulo incorporado se incluyó en Python 2.6. Cualquier proyecto que admita versiones de Python <2.6 debe tener un respaldo. En muchos casos, ese retroceso es simplejson.

thedz
fuente
4

Aquí hay una comparación (ahora desactualizada) de las bibliotecas Python json:

Comparación de módulos JSON para Python ( enlace de archivo )

Independientemente de los resultados en esta comparación, debe usar la biblioteca estándar json si está en Python 2.6. Y ... también podría usar simplejson de lo contrario.

Van Gale
fuente
2

El módulo simplejson es simplemente 1,5 veces más rápido que json (en mi computadora, con simplejson 2.1.1 y Python 2.7 x86).

Si lo desea, puede probar el punto de referencia: http://abral.altervista.org/jsonpickle-bench.zip En mi PC, simplejson es más rápido que cPickle. ¡Me gustaría conocer también sus puntos de referencia!

Probablemente, como dijo Coady, la diferencia entre simplejson y json es que simplejson incluye _speedups.c. Entonces, ¿por qué los desarrolladores de Python no usan simplejson?

Jeko
fuente
2

En python3, si tiene una cadena de b'bytes', debe acceder jsonal .decode()contenido antes de poder cargarlo. simplejsonse encarga de esto para que puedas hacerlo simplejson.loads(byte_string).

voidnologo
fuente
Cambiado en la versión 3.6: s ahora puede ser de tipo bytes o bytearray. La codificación de entrada debe ser UTF-8, UTF-16 o UTF-32.
Mathieu Longtin
1

jsonparece más rápido que simplejsonen ambos casos de cargas y volcados en la última versión

Versiones probadas:

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

Resultados:

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

Para versiones:

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

json fue más rápido que simplejson durante la operación de volcados pero ambos mantuvieron la misma velocidad durante las operaciones de carga

jophine
fuente
0

Encontré esta pregunta cuando estaba buscando instalar simplejson para Python 2.6. Necesitaba usar el 'object_pairs_hook' de json.load () para cargar un archivo json como un OrderedDict. Al estar familiarizado con las versiones más recientes de Python, no me di cuenta de que el módulo json para Python 2.6 no incluye el 'object_pairs_hook', así que tuve que instalar simplejson para este propósito. Por experiencia personal, esta es la razón por la que uso simplejson en lugar del módulo json estándar.

BeeLabeille
fuente