Каковы различия между модулями Python json и simplejson?


381

Я видел много проектов, использующих simplejsonмодуль вместо jsonмодуля из стандартной библиотеки. Также есть много разных simplejsonмодулей. Зачем использовать эти альтернативы, вместо того, что в стандартной библиотеке?

Ответы:


391

json есть simplejson , добавлено в stdlib. Но поскольку он jsonбыл добавлен в simplejsonверсии 2.6, он имеет преимущество работы с несколькими версиями Python (2.4+).

simplejsonтакже обновляется чаще, чем Python, поэтому, если вам нужна (или вы хотите) последняя версия, лучше использовать ее simplejson, если это возможно.

На мой взгляд, хорошей практикой является использование одного или другого в качестве запасного варианта.

try:
    import simplejson as json
except ImportError:
    import json

2
Теперь, если бы я только мог заставить pyflakes перестать жаловатьсяredefinition of unused 'json'
Джеймс МакМэхон

5
Они не одинаковы и не совместимы, у simplejson есть JSONDecodeError, а у json есть ValueError
Bjorn

3
@BjornTipling JSONDecodeErrorявляется подклассомValueError
elhefe

30
Я не согласен с приведенным выше ответом, если у вас есть обновленный Python. Встроенная (отличный плюс !!!) библиотека Json в Python 2.7 работает так же быстро, как и simplejson, и содержит меньше ошибок, исправляемых юникодом. Смотрите ответ stackoverflow.com/a/16131316/78234
Таль Вайс

1
Кажется, что Python2.7 json принял simplejson v2.0.9, который намного отстает от нынешнего simplejson v3.6.5 на момент написания. Есть много улучшений, которые стоит импортировать просто
Кэндзи Ногучи

82

Я должен не согласиться с другими ответами: встроенная jsonбиблиотека (в Python 2.7) не обязательно медленнее, чем simplejson. У этого также нет этой раздражающей ошибки юникода .

Вот простой тест:

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)

И результаты на моей системе (Python 2.7.4, Linux 64-bit):

Сложные данные реального мира:
JSON сбрасывает 1,56666707993 секунды
SimpleJSON сбрасывает 2,25638604164 секунды
JSON загружает 2,71256899834 секунды
SimpleJSON загружает 1,29233884811 секунды

Простые данные:
json dumps 0.370109081268 секунд
simplejson dumps 0.574181079865 секунд
json load 0.422876119614 секунд
simplejson загрузок 0.270955085754 секунд

Для сброса, jsonбыстрее, чем simplejson. Для загрузки, simplejsonбыстрее.

Поскольку в настоящее время я занимаюсь созданием веб-службы, dumps()это важнее, и всегда предпочтительнее использовать стандартную библиотеку.

Кроме того, cjsonне обновлялся в течение последних 4 лет, поэтому я бы не стал его трогать.


Это вводит в заблуждение. Мой ответ ниже объясняет почему.
notbad.jpeg

2
На моем ПК с Win7 (процессор i7) json(CPython 3.5.0) на 68% | 45% быстрее на простых | сложных дампах и на 35% | 17% на простых | сложных нагрузках по simplejsonсравнению с v3.8.0 с ускорением C с использованием кода вашего теста. Поэтому я бы больше не использовал simplejson с этой настройкой.
МАБ

1
Я только что запустил это на Python 3.6.1 и jsonвыиграл или то же самое для всех тестов. На самом деле jsonэто чуть меньше, чем вдвое быстрее, чем сложный тест на создание реальных дампов данных!
CpILL

27

Все эти ответы не очень полезны, потому что они чувствительны ко времени .

Проведя собственное исследование, я обнаружил, что simplejsonон действительно быстрее встроенного, если вы обновите его до последней версии.

pip/easy_installхотел установить 2.3.2 на ubuntu 12.04, но после того, как узнал, что последняя simplejsonверсия на самом деле - 3.3.0, я обновил ее и перезапустил время тестирования.

  • simplejsonпримерно в 3 раза быстрее, чем встроенный jsonпри нагрузке
  • simplejsonпримерно на 30% быстрее, чем встроенный jsonна свалках

Отказ от ответственности:

Вышеприведенные операторы написаны на python-2.7.3 и simplejson 3.3.0 (с ускорением c). Чтобы убедиться, что мой ответ также не чувствителен ко времени, вы должны запустить свои собственные тесты, чтобы проверить, так как он сильно варьируется между версиями; нет простого ответа, который не чувствителен ко времени.

Как узнать, включены ли ускорения C в simplejson:

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

ОБНОВЛЕНИЕ: я недавно столкнулся с библиотекой под названием ujson, которая работает в ~ 3 раза быстрее, чем simplejsonс некоторыми базовыми тестами.


Спасибо за упоминание Ujson. Эта ведет меня в другую библиотеку RapidJSON, которая выглядит лучше поддерживаемой
MCMZL

"simplejson 3.3.0 (с ускорением c)", правда? будь честнее и проверь это без c ускорений.
Рейшин

не используйте ujson, он изобилует ошибками, утечками памяти и сбоями и не обновлялся уже довольно давно. Мы отказались от него и переключились на simplejson, так как он обладает большей функциональностью, чем json, и обновляется
amohr

21

Я тестировал json, simplejson и cjson.

  • CJSON самый быстрый
  • simplejson почти наравне с cjson
  • json примерно в 10 раз медленнее, чем 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

6
Пожалуйста, добавьте pastie для фактического тестового модуля.
Таль Вайс

4
какие версии Python и библиотеки в вопросе?
Anentropic

6
Это больше не правда. json в python2.7 - это улучшения производительности.
Зенг

11

Некоторые значения по-разному сериализуются между simplejson и json.

Примечательно, что экземпляры collections.namedtupleсериализуются как массивы, jsonно как объекты simplejson. Вы можете переопределить это поведение, передав namedtuple_as_object=Falseв simplejson.dump, но по умолчанию, поведение не совпадает.

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

7

Я обнаружил, что несовместимость API с Python 2.7 против simplejson 3.3.1 заключается в том, создает ли выходные данные объекты str или unicode. например

>>> from json import JSONDecoder
>>> jd = JSONDecoder()
>>> jd.decode("""{ "a":"b" }""")
{u'a': u'b'}

против

>>> from simplejson import JSONDecoder
>>> jd = JSONDecoder()
>>> jd.decode("""{ "a":"b" }""")
{'a': 'b'}

Если предпочтение состоит в том, чтобы использовать simplejson, то это можно устранить путем принудительной установки аргументной строки в unicode, например:

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

Принуждение требует знания оригинальной кодировки, например:

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

Это не решит проблему 40


6

Еще одна причина, по которой проекты используют simplejson, заключается в том, что встроенный json изначально не включал в себя ускорения C, поэтому разница в производительности была заметной.


5

Встроенный jsonмодуль включен в Python 2.6. Любые проекты, которые поддерживают версии Python <2.6, должны иметь запасной вариант. Во многих случаях этот запасной вариант есть simplejson.


4

Вот (ныне устаревшее) сравнение библиотек Python json:

Сравнение модулей JSON для Python ( ссылка на архив )

Независимо от результатов этого сравнения вы должны использовать стандартную библиотеку json, если вы используете Python 2.6. И ... в противном случае можно просто использовать simplejson.


2

Модуль simplejson просто в 1,5 раза быстрее, чем json (на моем компьютере с simplejson 2.1.1 и Python 2.7 x86).

Если вы хотите, вы можете попробовать тест: http://abral.altervista.org/jsonpickle-bench.zip На моем ПК simplejson работает быстрее, чем cPickle. Я хотел бы знать также ваши ориентиры!

Вероятно, как сказал Коуди, разница между simplejson и json заключается в том, что simplejson включает _speedups.c. Итак, почему разработчики Python не используют simplejson?


2

В python3, если у вас есть строка b'bytes', jsonвы должны .decode()загрузить содержимое, прежде чем сможете его загрузить. simplejsonзаботится об этом, так что вы можете просто сделать simplejson.loads(byte_string).


Изменено в версии 3.6: теперь s может иметь тип bytes или bytearray. Входная кодировка должна быть UTF-8, UTF-16 или UTF-32.
Матье Лонгтин

1

jsonкажется быстрее, чем simplejsonв обоих случаях загрузки и выгрузки в последней версии

Протестированные версии:

  • питон: 3.6.8
  • JSON: 2,0,9
  • simplejson: 3.16.0

Результаты:

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

Для версий:

  • питон: 3.7.4
  • JSON: 2,0,9
  • simplejson: 3.17.0

json был быстрее, чем simplejson при работе с дампами, но оба поддерживали одинаковую скорость при работе с нагрузками


0

Я столкнулся с этим вопросом, когда искал возможность установить simplejson для Python 2.6. Мне нужно было использовать 'object_pairs_hook' из json.load (), чтобы загрузить файл json как OrderedDict. Будучи знаком с более поздними версиями Python, я не осознавал, что модуль json для Python 2.6 не содержит 'object_pairs_hook', поэтому мне пришлось установить simplejson для этой цели. Исходя из личного опыта, именно поэтому я использую simplejson, а не стандартный модуль json.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.