2014-05-10 21 views
34

Tôi sử dụng python 2.7 và cố gắng chọn một đối tượng. Tôi tự hỏi sự khác biệt thực sự là gì giữa các giao thức dưa chua.Lựa chọn giao thức pickle của Python?

import numpy as np 
import pickle 
class data(object): 
    def __init__(self): 
     self.a = np.zeros((100, 37000, 3), dtype=np.float32) 

d = data() 
print "data size: ", d.a.nbytes/1000000. 
print "highest protocol: ", pickle.HIGHEST_PROTOCOL 
pickle.dump(d,open("noProt", 'w')) 
pickle.dump(d,open("prot0", 'w'), protocol=0) 
pickle.dump(d,open("prot1", 'w'), protocol=1) 
pickle.dump(d,open("prot2", 'w'), protocol=2) 


out >> data size: 44.4 
out >> highest protocol: 2 

sau đó tôi phát hiện ra rằng các tập tin lưu có kích cỡ khác nhau trên đĩa:

  • noProt: 177.6MB
  • prot0: 177.6MB
  • prot1: 44.4MB
  • prot2: 44.4 MB

Tôi biết rằng prot0 là một tệp văn bản có thể đọc được của con người, vì vậy tôi không muốn sử dụng nó. Tôi đoán giao thức 0 là giao thức mặc định.

Tôi tự hỏi sự khác nhau giữa các giao thức 1 và 2 là lý do tại sao tôi nên chọn một hay một giao thức khác?

Sử dụng tốt hơn, pickle hoặc cPickle là gì?

+13

"chọn" sẽ là một từ đồng nghĩa tốt cho "lựa chọn" trong tiêu đề này :) – chepner

+13

@chepner "Chọn con trỏ giao thức pickle python?" :) –

+5

@JonClements: ooh, tôi * rất * bị cám dỗ để chỉnh sửa tiêu đề ngay bây giờ! –

Trả lời

29

Từ pickle module data format documentation:

Hiện tại có 3 giao thức khác nhau có thể được sử dụng để tẩy.

  • Giao thức phiên bản 0 là giao thức ASCII gốc và tương thích ngược với các phiên bản trước của Python.
  • Giao thức phiên bản 1 là định dạng nhị phân cũ cũng tương thích với các phiên bản trước của Python.
  • Giao thức phiên bản 2 đã được giới thiệu trong Python 2.3. Nó cung cấp nhiều hơn nữa hiệu quả tẩy của các lớp học theo phong cách mới.

[...]

Nếu một giao thức không được xác định, giao thức 0 được sử dụng. Nếu giao thức được chỉ định làm giá trị âm hoặc HIGHEST_PROTOCOL, phiên bản giao thức cao nhất khả dụng sẽ được sử dụng.

Stick với giao thức phiên bản 2, đặc biệt nếu bạn đang sử dụng các lớp tùy biến bắt nguồn từ object (lớp kiểu mới). Mà mã hiện đại nhất hiện nay, những ngày này.

Trừ khi bạn cần phải duy trì tính tương thích ngược với các phiên bản Python cũ, đó là dễ dàng nhất để chỉ gắn bó với phiên bản giao thức cao nhất mà bạn có thể đặt tay của bạn về:

with open("prot2", 'wb') as pfile: 
    pickle.dump(d, pfile, protocol=pickle.HIGHEST_PROTOCOL) 

Bởi vì đây là một định dạng nhị phân, hãy chắc chắn để sử dụng 'wb' làm chế độ tệp!

cPicklepickle chủ yếu tương thích; sự khác biệt nằm trong API được cung cấp. Đối với hầu hết các trường hợp sử dụng, chỉ cần gắn bó với cPickle; nó nhanh hơn.Trích dẫn documentation một lần nữa:

Thứ nhất, cPickle có thể nhanh hơn lên đến 1000 lần so với dưa vì cựu được thực hiện trong C. Thứ hai, trong module cPickle các callables Pickler()Unpickler() là chức năng, không phải các lớp học. Điều này có nghĩa là bạn không thể sử dụng chúng để lấy được các lớp con tùy chỉnh và các lớp con chưa giải thích. Hầu hết các ứng dụng không cần chức năng này và sẽ được hưởng lợi từ hiệu năng được cải thiện rất nhiều của mô-đun cPickle.

+1

'pickle' là phiên bản C trong Python 3 và Python 3.4 sử dụng giao thức 3 [nhanh gấp hai lần giao thức 2] (http://stackoverflow.com/a/26860404/819417). –

+1

@CeesTimmerman: miễn là bạn không [viết các số nguyên nhỏ riêng lẻ] (http://stackoverflow.com/questions/24097507/why-pickle-version-4-is-slower-than-version-3) và do đó sẽ làm cho cải thiện tốc độ khung hình, nếu không nó sẽ chậm hơn. :-) Câu trả lời này được hướng tới Python 2, vì đó là những gì OP đang hỏi về. –

+0

Tôi thấy & đã thêm thẻ 'python-2.7'. Không phải là điểm chuẩn so sánh 3 và 4 thay vì 2 và 3 sao? –

3

Đối với những người sử dụng Python 3, có, tính đến Python 3.5, năm giao thức có thể để lựa chọn:

Hiện đang có 5 giao thức khác nhau có thể được sử dụng để tẩy. Càng cao giao thức được sử dụng, gần đây nhiều phiên bản của Python cần thiết để đọc dưa sản xuất [doc]:

  • Protocol version 0 là gốc giao thức “con người có thể đọc được” và là tương thích ngược với trước đó các phiên bản của Python.

  • Giao thức phiên bản 1 là định dạng nhị phân cũ cũng tương thích với các phiên bản trước của Python.

  • Giao thức phiên bản 2 đã được giới thiệu trong Python 2.3. Nó cung cấp nhiều hơn nữa hiệu quả tẩy của các lớp học theo phong cách mới. Tham khảo PEP 307 để biết thông tin về các cải tiến được đưa ra bởi giao thức 2.
  • Giao thức phiên bản 3 đã được thêm vào trong Python 3.0. Nó có sự hỗ trợ rõ ràng cho các đối tượng byte và không thể được giải thích bởi Python 2.x. Điều này là giao thức mặc định và giao thức được đề xuất khi yêu cầu tương thích với các phiên bản Python 3 khác.
  • Giao thức phiên bản 4 đã được thêm vào bằng Python 3.4. Nó thêm hỗ trợ cho các đối tượng rất lớn, tẩy nhiều loại đối tượng hơn và một số dữ liệu tối ưu hóa định dạng . Tham khảo PEP 3154 để biết thông tin về cải tiến mang bởi giao thức 4.

Một nguyên tắc chung là bạn nên sử dụng các giao thức cao nhất có thể đó là tương thích ngược với những gì bạn muốn sử dụng nó cho. Vì vậy, nếu bạn muốn nó tương thích ngược với Python 2, thì giao thức phiên bản 2 là một lựa chọn tốt, nếu bạn muốn nó tương thích ngược với tất cả các phiên bản Python thì phiên bản 1 là tốt. Nếu bạn không quan tâm đến tính tương thích ngược thì sử dụng pickle.HIGHEST_PROTOCOL sẽ tự động cung cấp cho bạn giao thức cao nhất cho phiên bản Python của bạn.

Cũng trong Python 3, nhập pickle sẽ tự động nhập triển khai C.

Một điểm cần lưu ý khác về tính tương thích là, theo mặc định, giao thức 3 và 4 sử dụng mã hóa unicode của chuỗi trong khi các giao thức trước đó thì không. Vì vậy, trong Python 3, nếu bạn tải một tập tin ngâm đã được ngâm trong Python 2, có thể bạn sẽ phải xác định rõ ràng mã hóa để tải nó đúng cách.

Các vấn đề liên quan