Pickle หรือ json?


114

ฉันต้องการที่จะบันทึกลงดิสก์น้อยdictวัตถุที่มีคีย์เป็นประเภทstrและค่านิยมที่มีints แล้วกู้คืนได้ สิ่งนี้:

{'juanjo': 2, 'pedro':99, 'other': 333}

ตัวเลือกที่ดีที่สุดคืออะไรและทำไม? Serialize ด้วยpickleหรือด้วยsimplejson?

ฉันใช้ Python 2.6


แปลงเป็นอะไร นอกจากนี้ในแง่ใดที่ดีกว่า ?
SilentGhost

10
ใน 2.6 คุณจะไม่ใช้simplejsonคุณจะใช้jsonโมดูลในตัว(ซึ่งมีอินเทอร์เฟซเหมือนกันทุกประการ)
Mike Graham

5
"ดีที่สุด"? ดีที่สุดสำหรับอะไร? ความเร็ว? ความซับซ้อน? ความยืดหยุ่น? ค่าใช้จ่าย?
ล็อต


คำตอบ:


68

หากคุณไม่มีข้อกำหนดด้านความสามารถในการทำงานร่วมกัน (เช่นคุณกำลังจะใช้ข้อมูลกับ Python) และรูปแบบไบนารีก็ใช้ได้แล้วให้ใช้cPickleซึ่งให้การทำให้อนุกรมออบเจ็กต์ Python เร็วมาก

หากคุณต้องการความสามารถในการทำงานร่วมกันหรือต้องการรูปแบบข้อความเพื่อจัดเก็บข้อมูลของคุณให้ใช้ JSON (หรือรูปแบบอื่น ๆ ที่เหมาะสมขึ้นอยู่กับข้อ จำกัด ของคุณ)


48
JSON น่าจะเร็วกว่า cPickle
มี.ค.

5
คำตอบของฉันเน้นข้อกังวลที่ฉันคิดว่าสำคัญที่สุดที่ต้องพิจารณาเมื่อเลือกวิธีแก้ปัญหาอย่างใดอย่างหนึ่ง ฉันไม่เรียกร้องใด ๆ เกี่ยวกับการเร็วกว่าอีกฝ่าย หาก JSON เร็วกว่าและเหมาะสมอย่างอื่นให้ไปกับ JSON! (กล่าวคือไม่มีเหตุผลที่คุณจะลงคะแนน)
Håvard S

10
ประเด็นของฉันคือไม่มีเหตุผลที่แท้จริงในการใช้cPickle(หรือpickle) ตามสถานที่ของคุณผ่าน JSON เมื่อฉันอ่านคำตอบของคุณครั้งแรกฉันคิดว่าเหตุผลอาจเป็นเรื่องความเร็ว แต่เนื่องจากไม่ใช่กรณีนี้ ... :)
แม

14
เกณฑ์มาตรฐานที่อ้างถึงโดย @mac จะทดสอบสตริงเท่านั้น ฉันทดสอบ str, int และ float แยกกันและพบว่า json ช้ากว่า cPickle ที่มีการทำให้เป็นอนุกรมแบบลอย แต่เร็วกว่าด้วยการยกเลิกการเข้ารหัสแบบลอย สำหรับ int (และ str) json จะเร็วกว่าทั้งสองวิธี ข้อมูลและรหัส: gist.github.com/marians/f1314446b8bf4d34e782
Marian

24
โปรโตคอลล่าสุดของ cPickle เร็วกว่า JSON ความคิดเห็นที่โหวตขึ้นเกี่ยวกับ JSON ที่เร็วกว่านั้นล้าสมัยไปแล้วภายในสองสามปี stackoverflow.com/a/39607169/1007353
JDiMatteo

104

ฉันชอบ JSON มากกว่าของดองสำหรับการทำให้เป็นอนุกรม การปลดสามารถเรียกใช้รหัสโดยอำเภอใจและการใช้pickleเพื่อถ่ายโอนข้อมูลระหว่างโปรแกรมหรือจัดเก็บข้อมูลระหว่างเซสชันถือเป็นช่องโหว่ด้านความปลอดภัย JSON ไม่แนะนำช่องโหว่ด้านความปลอดภัยและเป็นมาตรฐานดังนั้นโปรแกรมในภาษาต่างๆจึงสามารถเข้าถึงข้อมูลได้หากคุณต้องการ


ขอบคุณ อย่างไรก็ตามฉันจะทิ้งและโหลดในโปรแกรมเดียวกัน
Juanjo Conti

2
แม้ว่าความเสี่ยงด้านความปลอดภัยในแอปพลิเคชันปัจจุบันของคุณอาจมีความเสี่ยงต่ำ แต่ JSON ช่วยให้คุณสามารถปิดทั้งหมดได้
Mike Graham

4
เราสามารถสร้างไวรัสดองที่ดองตัวเองลงในทุกสิ่งที่ดองหลังจากโหลด ด้วย json สิ่งนี้เป็นไปไม่ได้
ผู้ใช้

2
นอกเหนือจากความปลอดภัยแล้ว JSON ยังมีข้อได้เปรียบเพิ่มเติมที่ทำให้การย้ายข้อมูลเป็นเรื่องง่ายดังนั้นคุณสามารถโหลดข้อมูลที่แอปพลิเคชันของคุณบันทึกไว้ในเวอร์ชันเก่าได้ ในขณะเดียวกันคุณสามารถเพิ่มฟิลด์หรือแทนที่โครงสร้างย่อยทั้งหมด การเขียนตัวแปลงดังกล่าว (การโยกย้าย) สำหรับ dict / list นั้นตรงไปตรงมา แต่เมื่อใช้ Pickle คุณจะมีปัญหาในการโหลดตั้งแต่แรกก่อนที่คุณจะคิดแปลงได้
vog

2
ฉันไม่ได้คิดเกี่ยวกับแง่มุมนี้ (ความปลอดภัยและความสามารถสำหรับวัตถุดองในการเรียกใช้รหัสโดยพลการ) ขอบคุณที่ชี้ให้ดู!
CaffeinatedMike

43

คุณอาจพบว่าสิ่งนี้น่าสนใจโดยมีแผนภูมิให้เปรียบเทียบ: http://kovshenin.com/archives/pickle-vs-json-which-is-faster/


1
บทความนี้เปรียบเทียบประสิทธิภาพที่เกี่ยวข้องกับสตริงเท่านั้น นี่คือสคริปต์ที่คุณสามารถเรียกใช้เพื่อทดสอบสตริงการลอยและการเชื่อมต่อแยกกัน: gist.github.com/marians/f1314446b8bf4d34e782
Marian


20

หากคุณคำนึงถึงความเร็วและพื้นที่เป็นหลักให้ใช้ cPickle เนื่องจาก cPickle เร็วกว่า JSON

หากคุณกังวลเกี่ยวกับความสามารถในการทำงานร่วมกันความปลอดภัยและ / หรือความสามารถในการอ่านของมนุษย์ให้ใช้ JSON


ผลการทดสอบที่อ้างถึงในคำตอบอื่น ๆ ได้รับการบันทึกไว้ในปี 2010 และการทดสอบที่อัปเดตในปี 2559 ด้วย cPickle protocol 2 จะแสดง:

  • cPickle โหลดเร็วขึ้น 3.8 เท่า
  • cPickle อ่านเร็วขึ้น 1.5 เท่า
  • cPickle เข้ารหัสที่เล็กกว่าเล็กน้อย

สร้างสิ่งนี้ด้วยตัวคุณเองด้วยส่วนสำคัญนี้ซึ่งอ้างอิงตามเกณฑ์มาตรฐานของ Konstantin ที่อ้างถึงในคำตอบอื่น ๆ แต่ใช้ cPickle กับ protocol 2 แทนการดองและใช้ json แทน simplejson (เนื่องจากjson เร็วกว่า simplejson ) เช่น

wget https://gist.github.com/jdimatteo/af317ef24ccf1b3fa91f4399902bb534/raw/03e8dbab11b5605bc572bc117c8ac34cfa959a70/pickle_vs_json.py
python pickle_vs_json.py

ผลลัพธ์ด้วย python 2.7 บนโปรเซสเซอร์ Xeon ปี 2015 ที่เหมาะสม:

Dir Entries Method  Time    Length

dump    10  JSON    0.017   1484510
load    10  JSON    0.375   -
dump    10  Pickle  0.011   1428790
load    10  Pickle  0.098   -
dump    20  JSON    0.036   2969020
load    20  JSON    1.498   -
dump    20  Pickle  0.022   2857580
load    20  Pickle  0.394   -
dump    50  JSON    0.079   7422550
load    50  JSON    9.485   -
dump    50  Pickle  0.055   7143950
load    50  Pickle  2.518   -
dump    100 JSON    0.165   14845100
load    100 JSON    37.730  -
dump    100 Pickle  0.107   14287900
load    100 Pickle  9.907   -

Python 3.4 ที่มี pickle protocol 3 นั้นเร็วกว่า


11

JSON หรือของดอง? วิธีการเกี่ยวกับ JSON และดอง! คุณสามารถใช้jsonpickle. ใช้งานง่ายและไฟล์บนดิสก์สามารถอ่านได้เนื่องจากเป็น JSON

http://jsonpickle.github.com/


2
มีใครเปรียบเทียบประสิทธิภาพของมันเทียบกับตัวเลือกหรือไม่? ประสิทธิภาพเทียบได้กับ json ดิบที่เห็นที่นี่benfrederickson.com/dont-pickle-your-dataหรือไม่
Josep Valls

นี่ไม่ใช่เกณฑ์มาตรฐานที่หลากหลาย แต่ฉันมีเกมที่มีอยู่แล้วซึ่งมันบันทึกระดับโดยใช้ดอง (python3) ฉันต้องการลอง jsonpickle สำหรับแง่มุมที่มนุษย์อ่านได้ - อย่างไรก็ตามการบันทึกระดับนั้นช้าลงอย่างน่าเศร้า 1597ms สำหรับ jsonpickle และ 88ms หรือดองปกติในการบันทึกระดับ สำหรับโหลดระดับ 1604ms สำหรับ jsonpickle และ 388 สำหรับดอง สงสารที่ฉันชอบบันทึกที่มนุษย์อ่านได้
Neil McGill

ฉันทดสอบสิ่งนี้ในระบบการซื้อขายของเราความสามารถในการอ่านมาพร้อมกับค่าปรับความเร็วในการทำให้เป็นซีเรียลไลเซชั่น + การดีซีเรียลไลเซชั่นประมาณ 2 เท่าเมื่อเทียบกับของดอง ดีสำหรับสิ่งอื่น ๆ แม้ว่า
nurettin

6

ฉันได้ลองหลายวิธีและพบว่าการใช้ cPickle กับการตั้งค่าอาร์กิวเมนต์โปรโตคอลของวิธีการทิ้งเป็น: cPickle.dumps(obj, protocol=cPickle.HIGHEST_PROTOCOL)เป็นวิธีการถ่ายโอนข้อมูลที่เร็วที่สุด

import msgpack
import json
import pickle
import timeit
import cPickle
import numpy as np

num_tests = 10

obj = np.random.normal(0.5, 1, [240, 320, 3])

command = 'pickle.dumps(obj)'
setup = 'from __main__ import pickle, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("pickle:  %f seconds" % result)

command = 'cPickle.dumps(obj)'
setup = 'from __main__ import cPickle, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("cPickle:   %f seconds" % result)


command = 'cPickle.dumps(obj, protocol=cPickle.HIGHEST_PROTOCOL)'
setup = 'from __main__ import cPickle, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("cPickle highest:   %f seconds" % result)

command = 'json.dumps(obj.tolist())'
setup = 'from __main__ import json, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("json:   %f seconds" % result)


command = 'msgpack.packb(obj.tolist())'
setup = 'from __main__ import msgpack, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("msgpack:   %f seconds" % result)

เอาท์พุท:

pickle         :   0.847938 seconds
cPickle        :   0.810384 seconds
cPickle highest:   0.004283 seconds
json           :   1.769215 seconds
msgpack        :   0.270886 seconds

4

ส่วนตัวผมมักชอบ JSON เนื่องจากข้อมูลที่เป็นมนุษย์สามารถอ่านได้ แน่นอนว่าหากคุณต้องการจัดลำดับสิ่งที่ JSON จะไม่ใช้มากกว่าใช้ของดอง

แต่สำหรับการจัดเก็บข้อมูลส่วนใหญ่คุณไม่จำเป็นต้องทำให้เป็นอนุกรมอะไรแปลก ๆ และ JSON นั้นง่ายกว่ามากและช่วยให้คุณเปิดขึ้นมาในโปรแกรมแก้ไขข้อความและตรวจสอบข้อมูลด้วยตัวเองได้เสมอ

ความเร็วเป็นสิ่งที่ดี แต่สำหรับชุดข้อมูลส่วนใหญ่ความแตกต่างมีเล็กน้อย โดยทั่วไป Python ไม่เร็วเกินไป



1
จริง แต่สำหรับ100องค์ประกอบในรายการความแตกต่างนั้นไม่สำคัญอย่างยิ่งต่อสายตามนุษย์ แตกต่างอย่างแน่นอนเมื่อทำงานกับชุดข้อมูลขนาดใหญ่
rickcnagy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.