Quais são as diferenças entre os módulos Python json e simplejson?

381

Eu já vi muitos projetos usando o simplejsonmódulo em vez do jsonmódulo da Biblioteca Padrão. Além disso, existem muitos simplejsonmódulos diferentes . Por que usar essas alternativas, em vez da alternativa na Biblioteca Padrão?

Lakshman Prasad
fonte

Respostas:

391

json é simplejson adicionado ao stdlib. Mas desde que jsonfoi adicionado no 2.6, simplejsontem a vantagem de trabalhar em mais versões do Python (2.4+).

simplejsontambém é atualizado com mais frequência que o Python; portanto, se você precisar (ou quiser) da versão mais recente, é melhor usar- simplejsonse, se possível.

Uma boa prática, na minha opinião, é usar um ou outro como substituto.

try:
    import simplejson as json
except ImportError:
    import json
Devin Jeanpierre
fonte
2
Agora, se eu só poderia obter pyflakes de parar de reclamarredefinition of unused 'json'
James McMahon
5
Eles não são os mesmos, nem compatível, simplejson tem uma JSONDecodeError e JSON tem uma ValueError
Bjorn
3
@BjornTipling JSONDecodeErroré uma subclasse deValueError
elhefe
30
Não concordo com a resposta acima, supondo que você tenha um Python atualizado. A biblioteca Json (ótima mais !!!) incorporada no Python 2.7 é tão rápida quanto o simplejson e possui menos bugs unicode recusados ​​a serem corrigidos. Veja a resposta stackoverflow.com/a/16131316/78234
Tal Weiss
11
Parece que o json do Python2.7 adotou o simplejson v2.0.9, que está muito atrás do atual simplejson v3.6.5 até o momento da escrita. Existem muitas melhorias no valor da simplejson importação
Kenji Noguchi
82

Eu tenho que discordar das outras respostas: a jsonbiblioteca interna (no Python 2.7) não é necessariamente mais lenta que simplejson. Ele também não possui esse bug unicode irritante .

Aqui está uma referência simples:

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)

E os resultados no meu sistema (Python 2.7.4, Linux de 64 bits):

Dados complexos do mundo real:
json dumps 1.56666707993 segundos
simplejson dumps 2.25638604164 segundos
json carrega 2.71256899834 segundos
simplejson carrega 1.29233884811 segundos

Dados simples:
json dumps 0.370109081268 segundos
simplejson dumps 0.574181079865 segundos
json carrega 0.422876119614 segundos
simplejson carrega 0.270955085754 segundos

Para dumping, jsoné mais rápido que simplejson. Para carregar, simplejsoné mais rápido.

Como atualmente estou construindo um serviço da Web, dumps()é mais importante - e sempre é preferível o uso de uma biblioteca padrão.

Além disso, cjsonnão foi atualizado nos últimos 4 anos, por isso não o toquei.

Tal Weiss
fonte
Isso é enganoso. Minha resposta abaixo explica o porquê.
notbad.jpeg
2
No meu PC Win7 (CPU i7), o json(CPython 3.5.0) é 68% | 45% mais rápido em despejos simples e complexos e 35% em 17% em cargas simples e complexas wrt simplejsonv3.8.0 com acelerações C usando seu código de referência. Portanto, eu não usaria mais o simplejson nessa configuração.
mab
11
Acabei de executar isso no Python 3.6.1 e jsonganha ou é o mesmo para todos os testes. De fato, jsoné um pouco menos do que o dobro do teste complexo de despejo de dados do mundo real!
CpILL
27

Todas essas respostas não são muito úteis porque são sensíveis ao tempo .

Depois de fazer algumas pesquisas, descobri que simplejsoné realmente mais rápido que o incorporado, se você o mantiver atualizado para a versão mais recente.

pip/easy_installqueria instalar o 2.3.2 no ubuntu 12.04, mas depois de descobrir a simplejsonversão mais recente é realmente a 3.3.0, então eu a atualizei e refiz os testes de tempo.

  • simplejsoné cerca de 3x mais rápido que o embutido jsonem cargas
  • simplejsoné cerca de 30% mais rápido que o embutido jsonnos lixões

Aviso Legal:

As instruções acima estão em python-2.7.3 e simplejson 3.3.0 (com acelerações c) E para garantir que minha resposta também não seja sensível ao tempo, você deve executar seus próprios testes para verificar, pois varia muito entre as versões; não há uma resposta fácil que não seja sensível ao tempo.

Como saber se as acelerações C estão ativadas no simplejson:

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

UPDATE: Recentemente, deparei-me com uma biblioteca chamada ujson que está executando ~ 3x mais rápido do que simplejsonem alguns testes básicos.

notbad.jpeg
fonte
Obrigado por mencionar ujson. Este me levam a outra biblioteca RapidJSON que parece melhor mantido
MCMZL
"simplejson 3.3.0 (com acelerações c)" oh sério? seja mais honesto e teste-o sem c speedups.
Reishin
Não use o ujson, ele está cheio de bugs, vazamentos de memória e travamentos e não é atualizado há algum tempo. Nós o abandonamos e mudamos para o simplejson, pois ele tem mais funcionalidades do que o json e é atualizado
amohr 23/01
21

Estive comparando json, simplejson e cjson.

  • cjson é o mais rápido
  • simplejson está quase a par com cjson
  • json é cerca de 10x mais 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
fonte
6
Por favor, adicione uma pasta para o módulo de teste real.
Tal Weiss
4
quais versões do Python e as bibliotecas em questão?
Anentropic
6
Isso não é mais verdade. json em python2.7 é melhorias de desempenho.
Zengr 12/07/2013
11

Alguns valores são serializados de maneira diferente entre simplejson e json.

Notavelmente, as instâncias de collections.namedtuplesão serializadas como matrizes por, jsonmas como objetos por simplejson. Você pode substituir esse comportamento passando namedtuple_as_object=Falsepara simplejson.dump, mas por padrão os comportamentos não coincidem.

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

Uma incompatibilidade de API que encontrei, com Python 2.7 vs simplejson 3.3.1, é se a saída produz objetos str ou unicode. por exemplo

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

Se a preferência for usar simplejson, isso poderá ser resolvido coagindo a cadeia de argumentos a unicode, como em:

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

A coerção exige conhecer o conjunto de caracteres original, por exemplo:

>>> 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 é o problema não corrigido 40

jjc
fonte
6

Outro motivo pelo qual os projetos usam o simplejson é que o json interno não incluía originalmente suas acelerações em C, portanto a diferença de desempenho era perceptível.

A. Coady
fonte
5

O jsonmódulo embutido foi incluído no Python 2.6. Todos os projetos que suportam versões do Python <2.6 precisam ter um fallback. Em muitos casos, esse fallback é simplejson.

thedz
fonte
4

Aqui está (uma desatualizada) comparação das bibliotecas Python json:

Comparando Módulos JSON para Python ( link do arquivo morto) )

Independentemente dos resultados desta comparação, você deve usar a biblioteca padrão json se estiver no Python 2.6. E .. pode muito bem apenas usar simplejson caso contrário.

Van Gale
fonte
2

O módulo simplejson é simplesmente 1,5 vezes mais rápido que o json (no meu computador, com o simplejson 2.1.1 e o Python 2.7 x86).

Se desejar, você pode tentar o benchmark: http://abral.altervista.org/jsonpickle-bench.zip No meu PC, o simplejson é mais rápido que o cPickle. Gostaria de conhecer também seus benchmarks!

Provavelmente, como disse Coady, a diferença entre simplejson e json é que simplejson inclui _speedups.c. Então, por que os desenvolvedores python não usam o simplejson?

Jeko
fonte
2

No python3, se você tiver uma sequência de b'bytes', jsonprecisará .decode()do conteúdo antes de poder carregá-lo. simplejsoncuida disso para que você possa fazer simplejson.loads(byte_string).

voidnologo
fonte
Alterado na versão 3.6: s agora pode ser do tipo bytes ou bytearray. A codificação de entrada deve ser UTF-8, UTF-16 ou UTF-32.
Mathieu Longtin
1

json parece mais rápido que simplejson nos dois casos de cargas e lixões na versão mais recente

Versões testadas:

  • 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 versões:

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

O json foi mais rápido que o simplejson durante a operação de despejo, mas ambos mantiveram a mesma velocidade durante as operações de carregamento

jophine
fonte
0

Me deparei com essa pergunta, pois estava procurando instalar o simplejson para Python 2.6. Eu precisava usar o 'object_pairs_hook' de json.load () para carregar um arquivo json como um OrderedDict. Por estar familiarizado com versões mais recentes do Python, não percebi que o módulo json para o Python 2.6 não inclui o 'object_pairs_hook', portanto tive que instalar o simplejson para esse fim. Por experiência pessoal, é por isso que eu uso simplejson em oposição ao módulo json padrão.

BeeLabeille
fonte