Apa perbedaan antara modul Python json dan simplejson?

381

Saya telah melihat banyak proyek menggunakan simplejsonmoduljson modul dari Perpustakaan Standar. Juga, ada banyak simplejsonmodul berbeda . Mengapa menggunakan alternatif ini, alih-alih yang ada di Perpustakaan Standar?

Lakshman Prasad
sumber

Jawaban:

391

json adalah simplejson , ditambahkan ke stdlib. Tapi sejak jsonditambahkan di 2.6,simplejson memiliki keuntungan bekerja pada lebih banyak versi Python (2.4+).

simplejson juga diperbarui lebih sering daripada Python, jadi jika Anda perlu (atau ingin) versi terbaru, yang terbaik adalah menggunakan simplejson sendiri, jika memungkinkan.

Menurut saya, praktik yang baik adalah menggunakan satu atau yang lain sebagai mundur.

try:
    import simplejson as json
except ImportError:
    import json
Devin Jeanpierre
sumber
2
Sekarang jika saya hanya bisa membuat kepingan salju untuk berhenti mengeluh tentangredefinition of unused 'json'
James McMahon
5
Mereka tidak sama atau tidak kompatibel, simplejson memiliki JSONDecodeError dan json memiliki ValueError
Bjorn
3
@BjornTipling JSONDecodeErroradalah subclass dariValueError
elhefe
30
Saya tidak setuju dengan jawaban di atas dengan asumsi Anda memiliki Python terbaru. Pustaka Json built-in (hebat plus !!!) di Python 2.7 sama cepatnya dengan simplejson dan memiliki lebih sedikit bug unicode yang ditolak untuk diperbaiki. Lihat jawaban stackoverflow.com/a/16131316/78234
Tal Weiss
1
Tampaknya json Python2.7 mengadopsi simplejson v2.0.9 yang jauh di belakang simplejson v3.6.5 saat penulisan. Ada banyak perbaikan yang sebanding dengan impor simplejson
Kenji Noguchi
82

Saya harus tidak setuju dengan jawaban lain: built in jsonlibrary (dengan Python 2.7) belum tentu lebih lambat daripada simplejson. Juga tidak memiliki bug unicode yang mengganggu ini .

Berikut ini adalah patokan sederhana:

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)

Dan hasilnya di sistem saya (Python 2.7.4, Linux 64-bit):

Data dunia nyata yang kompleks:
json dumps 1.56666707993 detik
simplejson dumps 2.25638604164 detik
json memuat 2.71256899834 detik
simplejson memuat 1.29233884811 detik

Data sederhana:
json dumps 0,370109081268 detik
simplejson dumps 0,574181079865 detik
json memuat 0,422876119614 detik
simplejson load 0,270955085754 detik

Untuk dumping, jsonlebih cepat dari simplejson. Untuk memuat, simplejsonlebih cepat.

Karena saya sedang membangun layanan web, dumps()lebih penting — dan menggunakan perpustakaan standar selalu lebih disukai.

Juga, cjsontidak diperbarui dalam 4 tahun terakhir, jadi saya tidak akan menyentuhnya.

Tal Weiss
sumber
Ini menyesatkan. Jawaban saya di bawah menjelaskan alasannya.
notbad.jpeg
2
Pada PC Win7 saya (CPU i7), json(CPython 3.5.0) adalah 68% | 45% lebih cepat pada dump sederhana | kompleks dan 35% | 17% pada beban sederhana | kompleks wrt simplejsonv3.8.0 dengan speedup C menggunakan kode benchmark Anda. Oleh karena itu, saya tidak akan menggunakan simplejson lagi dengan pengaturan ini.
mab
1
Saya hanya menjalankan ini di Python 3.6.1 dan jsonmenang atau sama untuk semua tes. Bahkan jsonsedikit di bawah dua kali lebih cepat dari tes kesedihan data dunia nyata yang kompleks!
CpILL
27

Semua jawaban ini tidak terlalu membantu karena mereka sensitif terhadap waktu .

Setelah melakukan riset sendiri, saya menemukan bahwa simplejsonmemang lebih cepat daripada builtin, jika Anda tetap memperbaruinya ke versi terbaru.

pip/easy_installingin menginstal 2.3.2 di ubuntu 12.04, tetapi setelah mengetahui simplejsonversi terbaru sebenarnya 3.3.0, jadi saya memperbaruinya dan mengulang tes waktu.

  • simplejsonsekitar 3x lebih cepat dari builtin jsonpada beban
  • simplejsonsekitar 30% lebih cepat dari builtin jsondi tempat pembuangan

Penolakan:

Pernyataan di atas adalah dalam python-2.7.3 dan simplejson 3.3.0 (dengan c speedups) Dan untuk memastikan jawaban saya juga tidak peka waktu, Anda harus menjalankan tes Anda sendiri untuk memeriksa karena sangat bervariasi antara versi; tidak ada jawaban mudah yang tidak peka waktu.

Bagaimana cara mengetahui apakah speedup C diaktifkan di simplejson:

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

UPDATE: Saya baru-baru ini menemukan perpustakaan bernama ujson yang melakukan ~ 3x lebih cepat daripada simplejsondengan beberapa tes dasar.

notbad.jpeg
sumber
Terima kasih telah menyebutkan ujson. Yang ini membawa saya ke perpustakaan lain, RapidJSON yang terlihat lebih terawat
MCMZL
"simplejson 3.3.0 (dengan c speedups)" oh benarkah? menjadi lebih jujur ​​dan mengujinya tanpa c speedups.
Reishin
jangan gunakan ujson, ini dipenuhi dengan bug dan kebocoran memori dan crasher dan belum diperbarui dalam beberapa waktu. Kami telah membuangnya dan beralih ke simplejson karena memiliki lebih banyak fungsi daripada json dan diperbarui
amohr
21

Saya telah melakukan benchmark json, simplejson dan cjson.

  • cjson adalah yang tercepat
  • simplejson hampir setara dengan cjson
  • json sekitar 10x lebih lambat dari 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
sumber
6
Silakan tambahkan pastie untuk modul tes yang sebenarnya.
Tal Weiss
4
versi Python dan libs yang dimaksud?
Anentropic
6
Ini tidak benar lagi. json di python2.7 adalah peningkatan kinerja.
zengr
11

Beberapa nilai di-serialisasi secara berbeda antara simplejson dan json.

Khususnya, contoh collections.namedtupleserialisasi sebagai array oleh jsontetapi sebagai objek olehsimplejson . Anda bisa mengubah perilaku ini dengan melewati namedtuple_as_object=Falseuntuk simplejson.dump, tetapi secara default perilaku tidak cocok.

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

Ketidakcocokan API yang saya temukan, dengan Python 2.7 vs simplejson 3.3.1 adalah apakah output menghasilkan objek str atau unicode. misalnya

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

Jika preferensi adalah menggunakan simplejson, maka ini dapat diatasi dengan memaksa string argumen ke unicode, seperti pada:

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

Paksaan memang membutuhkan mengetahui rangkaian karakter asli, misalnya:

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

Ini adalah masalah tidak akan diperbaiki 40

jjc
sumber
6

Alasan lain mengapa proyek menggunakan simplejson adalah bahwa builtin json pada awalnya tidak termasuk speedup C-nya, sehingga perbedaan kinerja terlihat.

A. Coady
sumber
5

jsonModul builtin disertakan dalam Python 2.6. Setiap proyek yang mendukung versi Python <2.6 perlu memiliki cadangan. Dalam banyak kasus, fallback itu adalah simplejson.

thedz
sumber
4

Berikut ini (sekarang usang) perbandingan perpustakaan Python json:

Membandingkan modul JSON untuk Python ( tautan arsip )

Terlepas dari hasil dalam perbandingan ini, Anda harus menggunakan json pustaka standar jika Anda menggunakan Python 2.6. Dan .. mungkin saja gunakan simplejson sebaliknya.

Van Gale
sumber
2

Modul simplejson hanya 1,5 kali lebih cepat dari json (Di komputer saya, dengan simplejson 2.1.1 dan Python 2.7 x86).

Jika mau, Anda dapat mencoba patokan: http://abral.altervista.org/jsonpickle-bench.zip Di PC saya simplejson lebih cepat daripada cPickle. Saya ingin tahu juga tolok ukur Anda!

Mungkin, seperti yang dikatakan Coady, perbedaan antara simplejson dan json adalah bahwa simplejson menyertakan _speedups.c. Jadi, mengapa tidak pengembang python menggunakan simplejson?

Jeko
sumber
2

Dalam python3, jika Anda string b'bytes', dengan jsonAnda harus .decode()konten sebelum Anda dapat memuatnya. simplejsonmengurus ini sehingga Anda bisa melakukannya simplejson.loads(byte_string).

voidnologo
sumber
Berubah dalam versi 3.6: s sekarang bisa dari tipe byte atau bytearray. Pengkodean input harus berupa UTF-8, UTF-16 atau UTF-32.
Mathieu Longtin
1

json sepertinya lebih cepat dari simplejson di kedua kasus memuat dan kesedihan di versi terbaru

Versi yang diuji:

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

Hasil:

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

Untuk versi:

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

json lebih cepat daripada simplejson selama operasi dump tetapi keduanya mempertahankan kecepatan yang sama selama operasi load

Jophine
sumber
0

Saya menemukan pertanyaan ini ketika saya ingin menginstal simplejson untuk Python 2.6. Saya perlu menggunakan 'object_pairs_hook' dari json.load () untuk memuat file json sebagai OrderedDict. Menjadi terbiasa dengan versi Python yang lebih baru, saya tidak menyadari bahwa modul json untuk Python 2.6 tidak termasuk 'object_pairs_hook' jadi saya harus menginstal simplejson untuk tujuan ini. Dari pengalaman pribadi inilah mengapa saya menggunakan simplejson yang bertentangan dengan modul json standar.

BeeLabeille
sumber