سؤال

لقد رأيت العديد من المشاريع باستخدام simplejson الوحدة النمطية بدلا من json الوحدة النمطية من المكتبة القياسية. أيضا، هناك العديد من مختلف simplejson وحدات. لماذا سيستخدم هذه البدائل، بدلا من واحد في المكتبة القياسية؟

هل كانت مفيدة؟

المحلول

json يكون simplejson, ، إضافة إلى Stdlib. لكن منذ json أضيفت في 2.6، simplejson لديه ميزة العمل على المزيد من إصدارات الثعبان (2.4+).

simplejson يتم تحديثه أيضا بشكل متكرر أكثر من Python، لذلك إذا كنت بحاجة إلى (أو تريد) أحدث إصدار، فمن الأفضل استخدامه simplejson نفسه، إن أمكن.

ممارسة جيدة، في رأيي، هي استخدام واحد أو الآخر كعطاس.

try:
    import simplejson as json
except ImportError:
    import json

نصائح أخرى

لا بد لي من عدم الاتفاق مع الإجابات الأخرى: المدمج json المكتبة (في بيثون 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)

والنتائج على نظامي (بيثون 2.7.4، لينكس 64 بت):

بيانات العالم الحقيقي المعقدة:
JSON مقالب 1.56666707993 ثانية
Simplejson مقالب 2.25638604164 ثانية
تحميل JSON 2.71256899834 ثانية
SimpleJson تحميل 1.29233884811 ثانية

بيانات بسيطة:
JSON DUMPS 0.370109081268 ثانية
مقالب Simplejson 0.574181079865 ثانية
JSON تحميل 0.422876119614 ثانية
Simplejson تحميل 0.270955085754 ثانية

للإغراق، json أسرع من ذلك simplejsonوبعد للتحميل، simplejson أسرع.

منذ أن أقوم حاليا ببناء خدمة ويب، dumps() هو أكثر أهمية - واستخدام مكتبة قياسية يفضل دائما.

أيضا، cjson لم يتم تحديثها في السنوات الأربع الماضية، لذلك لن أتطرق إليها.

كل هذه الإجابات ليست مفيدة للغاية لأنها وقت حساس.

بعد القيام ببعض البحوث الخاصة بي وجدت ذلك simplejson هو في الواقع أسرع من المدمج، إذا يمكنك الاحتفاظ بها على التحديث إلى أحدث إصدار.

pip/easy_install مطلوب لتثبيت 2.3.2 على Ubuntu 12.04، ولكن بعد العثور على أحدث simplejson الإصدار هو في الواقع 3.3.0، لذلك قمت بتحديثها وأروع الاختبارات الزمنية.

  • simplejson حوالي 3x أسرع من المدمج 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. هذا هو أداء ~ 3x أسرع من simplejson مع بعض الاختبارات الأساسية.

لقد كنت معيار JSON، Simplejson و Cjson.

  • CJSON أسرع
  • simplejson هو تقريبا على قدم المساواة مع cjson
  • JSON حوالي 10X أبطأ من 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

يتم تسليم بعض القيم بشكل مختلف بين 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]'

عدم توافق API الذي وجدته، مع Python 2.7 vs 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.

المدمجة json تم تضمين وحدة في بيثون 2.6. أي مشاريع تدعم إصدارات Python <2.6 تحتاج إلى الحصول على تراجع. في كثير من الحالات، هذا التراجع هو simplejson.

سبب آخر مشاريع تستخدم SimpleJson هو أن JSON المدمج لم يتضمن أصلا تسريع C، لذلك كان فرق الأداء ملحوظا.

إليك مقارنة الآن (عفا عليها الزمن الآن) من مكتبات بيثون JSON:

مقارنة وحدات JSON لبثون (أرشيف رابط)

بغض النظر عن النتائج في هذه المقارنة، يجب عليك استخدام المكتبة القياسية JSON إذا كنت في Python 2.6. و .. قد مجرد استخدام SimpleJson خلاف ذلك.

الوحدة النمطية Simplejsy هي ببساطة 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؟

في python3، إذا كنت سلسلة من b'bytes', ، مع json عليك أن .decode() المحتوى قبل أن تتمكن من تحميله. simplejson يعتني بهذا حتى تتمكن من القيام به simplejson.loads(byte_string).

صادفت هذه المسألة حيث كنت أتطلع إلى تثبيت SimpleJson for Python 2.6. كنت بحاجة لاستخدام "Object_Pairs_hook" من JSON.Load () لتحميل ملف JSON كترتيب. إن عدم دراية بالإصدارات الأخيرة من Python لم أكن أدرك أن وحدة JSON ل Python 2.6 لا تتضمن "Object_Pairs_hook" لذلك اضطررت إلى تثبيت SimpleJson لهذا الغرض. من تجربة شخصية، هذا هو السبب في أنني أستخدم SimpleJsy بدلا من وحدة JSON القياسية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top