Dưa chua hay json?


114

Tôi cần lưu vào đĩa một dictđối tượng nhỏ có các khóa thuộc loại strvà giá trị là ints và sau đó khôi phục nó . Một cái gì đó như thế này:

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

Lựa chọn tốt nhất là gì và tại sao? Nối tiếp nó với picklehoặc với simplejson?

Tôi đang sử dụng Python 2.6.


chuyển đổi nó sang cái gì? Ngoài ra, theo nghĩa nào tốt hơn ?
SilentGhost

10
Trong 2.6 bạn sẽ không sử dụng simplejson, bạn sẽ sử dụng jsonmô-đun nội trang (có cùng giao diện chính xác).
Mike Graham

5
"tốt"? Tốt nhất để làm gì? Tốc độ? Độ phức tạp? Uyển chuyển? Giá cả?
S.Lott


Câu trả lời:


68

Nếu bạn không có bất kỳ yêu cầu nào về khả năng tương tác (ví dụ: bạn chỉ định sử dụng dữ liệu với Python) và định dạng nhị phân là ổn, hãy sử dụng cPickle để tuần tự hóa đối tượng Python thực sự nhanh chóng.

Nếu bạn muốn khả năng tương tác hoặc bạn muốn một định dạng văn bản để lưu trữ dữ liệu của mình, hãy sử dụng JSON (hoặc một số định dạng thích hợp khác tùy thuộc vào các ràng buộc của bạn).


48
JSON dường như nhanh hơn cPickle.
mac

5
Câu trả lời của tôi nêu bật những mối quan tâm mà tôi nghĩ là quan trọng nhất cần xem xét khi chọn một trong hai giải pháp. Tôi không tuyên bố về việc nhanh hơn cái kia. Nếu JSON nhanh hơn VÀ nếu không, hãy sử dụng JSON! (Tức là, không có lý do cho xuống lá phiếu của bạn.)
Håvard S

10
Quan điểm của tôi là: không có lý do thực sự nào để sử dụng cPickle(hoặc pickle) dựa trên cơ sở của bạn trên JSON. Khi tôi lần đầu tiên đọc câu trả lời của bạn, tôi nghĩ lý do có thể là do tốc độ, nhưng vì đây không phải là trường hợp ... :)
mac

14
Điểm chuẩn được trích dẫn bởi @mac chỉ kiểm tra các chuỗi. Tôi đã thử nghiệm str, int và float riêng biệt và phát hiện ra rằng json chậm hơn cPickle với float serialization, nhưng nhanh hơn với float unserialization. Đối với int (và str), json nhanh hơn theo cả hai cách. Dữ liệu và mã: gist.github.com/marians/f1314446b8bf4d34e782
Marian

24
Giao thức mới nhất của cPickle hiện nhanh hơn JSON. Nhận xét được nhiều người bình chọn về việc JSON nhanh hơn đã lỗi thời trong một vài năm. stackoverflow.com/a/39607169/1007353
JDiMatteo 22/09/2016

104

Tôi thích JSON hơn pickle cho tuần tự hóa của mình. Unpickling có thể chạy mã tùy ý và sử dụng pickleđể truyền dữ liệu giữa các chương trình hoặc lưu trữ dữ liệu giữa các phiên là một lỗ hổng bảo mật. JSON không có lỗ hổng bảo mật và được tiêu chuẩn hóa, vì vậy dữ liệu có thể được truy cập bởi các chương trình bằng các ngôn ngữ khác nhau nếu bạn cần.


Cảm ơn. Dù sao thì tôi sẽ kết xuất và tải trong cùng một chương trình.
Juanjo Conti

2
Mặc dù các rủi ro bảo mật có thể thấp trong ứng dụng hiện tại của bạn, nhưng JSON cho phép bạn đóng toàn bộ.
Mike Graham

4
Người ta có thể tạo ra một loại vi-rút dưa muối tự ngấm vào mọi thứ được ngâm sau khi được tải. Với json điều này là không thể.
Người dùng

2
Ngoài bảo mật, JSON có một lợi thế bổ sung là nó giúp di chuyển dễ dàng, vì vậy bạn có thể tải dữ liệu đã được lưu bởi phiên bản ứng dụng cũ hơn của mình. Trong khi đó, bạn có thể đã thêm một trường hoặc thay thế toàn bộ cấu trúc con. Việc viết một trình chuyển đổi (chuyển đổi) như vậy cho dict / list là điều dễ hiểu, nhưng với Pickle, bạn sẽ gặp khó khăn khi tải nó ngay từ đầu, trước khi bạn có thể nghĩ đến việc chuyển đổi.
vog

2
Tôi đã không nghĩ về khía cạnh này (bảo mật và khả năng cho các đối tượng bị móc túi chạy mã tùy ý). Cảm ơn vì đã chỉ ra điều đó!
CaffeinatedMike vào

43

Bạn cũng có thể thấy điều này thú vị, với một số biểu đồ để so sánh: http://kovshenin.com/archives/pickle-vs-json-which-is-faster/


1
Bài viết so sánh hiệu suất chỉ liên quan đến chuỗi. Dưới đây là một kịch bản bạn có thể chạy để chuỗi kiểm tra, phao nổi và các ints riêng rẽ: gist.github.com/marians/f1314446b8bf4d34e782
Marian


20

Nếu bạn chủ yếu quan tâm đến tốc độ và dung lượng, hãy sử dụng cPickle vì cPickle nhanh hơn JSON.

Nếu bạn quan tâm hơn đến khả năng tương tác, bảo mật và / hoặc khả năng đọc của con người, thì hãy sử dụng JSON.


Các kết quả kiểm tra được tham chiếu trong các câu trả lời khác được ghi lại vào năm 2010 và các bài kiểm tra cập nhật vào năm 2016 với giao thức cPickle 2 cho thấy:

  • cPickle tải nhanh hơn 3,8 lần
  • cPickle đọc nhanh hơn 1,5 lần
  • mã hóa cPickle nhỏ hơn một chút

Tự sao chép lại điều này với ý chính này , dựa trên điểm chuẩn của Konstantin được tham chiếu trong các câu trả lời khác, nhưng sử dụng cPickle với giao thức 2 thay vì pickle và sử dụng json thay vì simplejson (vì json nhanh hơn simplejson ), ví dụ:

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

Kết quả với python 2.7 trên bộ xử lý Xeon 2015 tốt:

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 với giao thức pickle 3 thậm chí còn nhanh hơn.


11

JSON hay dưa chua? Còn JSON dưa chua! Bạn có thể sử dụng jsonpickle. Nó dễ sử dụng và tệp trên đĩa có thể đọc được vì nó là JSON.

http://jsonpickle.github.com/


2
Bất kỳ ai đã đánh giá hiệu suất của nó so với các tùy chọn? Nó có thể so sánh về hiệu suất như json thô như đã thấy ở đây benfrederickson.com/dont-pickle-your-data không?
Josep Valls

Đây không phải là một điểm chuẩn trên phạm vi rộng, nhưng tôi đã có một trò chơi hiện có trong đó nó đang lưu các cấp độ bằng cách sử dụng dưa chua (python3). Tôi muốn thử jsonpickle cho khía cạnh con người có thể đọc được - tuy nhiên, đáng buồn là các lần lưu cấp lại chậm hơn nhiều. 1597ms cho jsonpickle và 88ms hoặc dưa chua thông thường khi tiết kiệm mức. Đối với mức tải, 1604ms cho jsonpickle và 388 cho pickle. Thật tội nghiệp vì tôi thích những pha cứu thua có thể đọc được của con người.
Neil McGill

Tôi đã thử nghiệm điều này trong hệ thống giao dịch của chúng tôi, khả năng đọc được đi kèm với hình phạt tốc độ tuần tự hóa + deserialization khoảng gấp đôi so với dưa chua. Tuy nhiên, tuyệt vời cho bất cứ điều gì khác.
nurettin

6

Tôi đã thử một số phương pháp và phát hiện ra rằng việc sử dụng cPickle với việc đặt đối số giao thức của phương thức kết xuất là: cPickle.dumps(obj, protocol=cPickle.HIGHEST_PROTOCOL)là phương pháp kết xuất nhanh nhất.

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)

Đầu ra:

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

4

Cá nhân tôi thường thích JSON hơn vì dữ liệu có thể đọc được . Chắc chắn, nếu bạn cần tuần tự hóa thứ gì đó mà JSON sẽ không sử dụng, hơn là sử dụng pickle.

Nhưng đối với hầu hết việc lưu trữ dữ liệu, bạn sẽ không cần phải tuần tự hóa bất kỳ thứ gì kỳ lạ và JSON dễ dàng hơn nhiều và luôn cho phép bạn mở nó trong trình soạn thảo văn bản và tự mình kiểm tra dữ liệu.

Tốc độ là tốt, nhưng đối với hầu hết các bộ dữ liệu, sự khác biệt là không đáng kể; Python thường không quá nhanh.



1
Thật. Nhưng đối với 100các yếu tố trong một danh sách, sự khác biệt hoàn toàn không đáng kể đối với mắt người. Chắc chắn sẽ khác khi làm việc với các bộ dữ liệu lớn hơn.
rickcnagy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.