2011-09-21 53 views
34

Tôi vừa mới có một bài tập nơi tôi cần phải đặt một từ điển (trong đó mỗi khóa đề cập đến một danh sách) ở dạng ngâm. Vấn đề duy nhất là tôi không biết hình thức ngâm là gì. Bất cứ ai có thể chỉ cho tôi đúng hướng của một số nguồn lực tốt để giúp tôi tìm hiểu khái niệm này? Cảm ơn!Tìm hiểu về Pickling bằng Python

+34

http://docs.python.org/library/pickle.html là kết quả đầu tiên của Google cho "dưa chua", thậm chí đánh bại trang Wikipedia về rau được bảo quản. – geoffspear

+17

@Wooble: Tôi biết chủ đề hoàn toàn tắt của nó, nhưng tìm kiếm của Google thay đổi theo vị trí của bạn, lịch sử tìm kiếm, thậm chí cả lịch sử email/trò chuyện;). Nhưng có, +1 để trỏ đến tài liệu. – 0xc0de

+6

@ 0xc0de Phải. Đối với tôi mục đầu * là * rau được bảo quản. :-) Đoán tôi nên bắt đầu viết mã nhiều hơn. –

Trả lời

17

Trong khi những người khác đã chỉ ra các tài liệu Python trên module dưa, mà là một nguồn lực lớn, bạn cũng có thể xem Chapter 13: Serializing Python Objects của Lặn vào Python 3 bởi Mark Pilgrim.

+0

Cảm ơn bạn đã trỏ đến một tài nguyên giải thích * tại sao * bạn sẽ muốn chọn một đối tượng python. –

3

http://docs.python.org/library/pickle.html#example

import pickle 

data1 = {'a': [1, 2.0, 3, 4+6j], 
     'b': ('string', u'Unicode string'), 
     'c': None} 

selfref_list = [1, 2, 3] 
selfref_list.append(selfref_list) 

output = open('data.pkl', 'wb') 

# Pickle dictionary using protocol 0. 
pickle.dump(data1, output) 

# Pickle the list using the highest protocol available. 
pickle.dump(selfref_list, output, -1) 

output.close() 
66

Các module dưa thực hiện một thuật toán cơ bản, nhưng mạnh mẽ cho serializing và de-serializing một cấu trúc đối tượng Python.

phẩm làm sạch - là quá trình trong đó một hệ thống phân cấp đối tượng Python được chuyển đổi thành một dòng byte, và Unpickling - là hoạt động ngược lại, nhờ đó mà một dòng byte được chuyển đổi trở lại thành một hệ thống phân cấp đối tượng.

phẩm làm sạch (và unpickling) là cách gọi khác như serialization, marshalling, hoặc phẳng.

import pickle 

data1 = {'a': [1, 2.0, 3, 4+6j], 
     'b': ('string', u'Unicode string'), 
     'c': None} 

selfref_list = [1, 2, 3] 
selfref_list.append(selfref_list) 

output = open('data.pkl', 'wb') 

# Pickle dictionary using protocol 0. 
pickle.dump(data1, output) 

# Pickle the list using the highest protocol available. 
pickle.dump(selfref_list, output, -1) 

output.close() 

Để đọc từ một tập tin ngâm -

import pprint, pickle 

pkl_file = open('data.pkl', 'rb') 

data1 = pickle.load(pkl_file) 
pprint.pprint(data1) 

data2 = pickle.load(pkl_file) 
pprint.pprint(data2) 

pkl_file.close() 

nguồn - https://docs.python.org/2/library/pickle.html

+8

Đây chỉ là một trong những mẫu mã tốt nhất mà tôi từng thấy. Được định dạng đẹp và tuyệt vời gọn gàng. Cảm ơn bạn. – anon58192932

+1

Tôi không hiểu tại sao 'data1 = pickle.load (pkl_file)' không tải tệp hoàn chỉnh (data.pkl)? – Naive

+0

Việc tẩy có yêu cầu thông số đầu ra của tệp không? Làm cách nào để giữ cho đối tượng được tuần tự hóa lưu trữ nó ở nơi khác? – Praxiteles

3

Pickling trong Python được sử dụng để tuần tự hóa và loại bỏ các đối tượng Python, như từ điển trong trường hợp của bạn. Tôi thường sử dụng mô-đun cPickle vì nó có thể nhanh hơn nhiều so với mô-đun Pickle.

import cPickle as pickle  

def serializeObject(pythonObj): 
    return pickle.dumps(pythonObj, pickle.HIGHEST_PROTOCOL) 

def deSerializeObject(pickledObj): 
    return pickle.loads(pickledObj) 
19

phẩm làm sạch là một mini-ngôn ngữ có thể được sử dụng để chuyển đổi trạng thái có liên quan từ một đối tượng python vào một chuỗi, nơi chuỗi này duy nhất đại diện cho đối tượng. Sau đó (un) tẩy có thể được sử dụng để chuyển đổi chuỗi thành một đối tượng trực tiếp, bằng cách "xây dựng lại" đối tượng từ trạng thái đã lưu thành lập chuỗi.

>>> import pickle 
>>> 
>>> class Foo(object): 
... y = 1 
... def __init__(self, x): 
...  self.x = x 
...  return 
... def bar(self, y): 
...  return self.x + y 
... def baz(self, y): 
...  Foo.y = y 
...  return self.bar(y) 
... 
>>> f = Foo(2) 
>>> f.baz(3) 
5 
>>> f.y 
3 
>>> pickle.dumps(f) 
"ccopy_reg\n_reconstructor\np0\n(c__main__\nFoo\np1\nc__builtin__\nobject\np2\nNtp3\nRp4\n(dp5\nS'x'\np6\nI2\nsb." 

Những gì bạn có thể thấy ở đây là dưa không lưu mã nguồn cho lớp, nhưng lưu trữ tham chiếu đến định nghĩa lớp. Về cơ bản, bạn gần như có thể đọc chuỗi đã chọn… nó nói (tạm dịch), gọi hàm dựng lại của copy_reg, trong đó các đối số là lớp được xác định bởi __main__.Foo và sau đó thực hiện các công cụ khác ". Các thứ khác là trạng thái đã lưu của cá thể. Nếu bạn nhìn sâu hơn, bạn có thể trích xuất rằng "chuỗi x" được đặt thành "số nguyên 2" (khoảng: S'x'\np6\nI2). Đây thực sự là một phần được cắt bớt của chuỗi được chọn cho mục nhập từ điển… số dictf.__dict__, là {'x': 2}. Nếu bạn nhìn vào mã nguồn cho pickle, nó rất rõ ràng cung cấp một bản dịch cho từng loại đối tượng và hoạt động từ python để ngâm mã byte.

Cũng lưu ý rằng có các biến thể khác nhau của ngôn ngữ tẩy. Giao thức mặc định là giao thức 0, có thể đọc được nhiều hơn. Ngoài ra còn có giao thức 2, được hiển thị bên dưới (và 1,3 và 4, tùy thuộc vào phiên bản của python bạn đang sử dụng).

>>> pickle.dumps([1,2,3]) 
'(lp0\nI1\naI2\naI3\na.' 
>>> 
>>> pickle.dumps([1,2,3], -1) 
'\x80\x02]q\x00(K\x01K\x02K\x03e.' 

Một lần nữa, nó vẫn là một phương ngữ của ngôn ngữ tẩy, và bạn có thể thấy rằng các chuỗi giao thức 0 nói "có được một danh sách, bao gồm I1, I2, I3", trong khi các giao thức 2 là khó khăn hơn để đọc, nhưng cũng nói như vậy. Bit đầu tiên \x80\x02 chỉ ra rằng đó là giao thức 2 - sau đó bạn có ] mà nói đó là một danh sách, sau đó một lần nữa bạn có thể thấy các số nguyên 1,2,3 trong đó. Một lần nữa, kiểm tra mã nguồn cho dưa chua để xem bản đồ chính xác cho ngôn ngữ tẩy.

Để đảo ngược quá trình tẩy cho một chuỗi, hãy sử dụng tải/tải.

>>> p = pickle.dumps([1,2,3]) 
>>> pickle.loads(p) 
[1, 2, 3] 
+2

Là một người mới bắt đầu, tôi đã có câu hỏi này trong đầu của tôi, những loại công cụ không dưa làm ở bên trong? Câu trả lời này giải quyết rằng nhiều hơn những người khác. –

2

Mô đun pickle thực hiện một thuật toán cơ bản, nhưng mạnh mẽ để sắp xếp và hủy tuần tự cấu trúc đối tượng Python. "Pickling" là quá trình trong đó một hệ thống phân cấp đối tượng Python được chuyển đổi thành một dòng byte, và "unpickling" là hoạt động nghịch đảo, theo đó một dòng byte được chuyển đổi trở lại thành một hệ thống phân cấp đối tượng. Việc tẩy (và tháo ghim) được gọi là "serialization", "marshaling" hoặc "flattening", tuy nhiên, để tránh nhầm lẫn, các thuật ngữ được sử dụng ở đây là "tẩy" và "tháo nút".

Mô-đun dưa có một người anh em họ được tối ưu hóa được gọi là mô-đun cPickle. Như tên gọi của nó, cPickle được viết bằng C, vì vậy nó có thể nhanh hơn đến 1000 lần so với dưa chua. Tuy nhiên, nó không hỗ trợ lớp con của các lớp Pickler() và Unpickler(), bởi vì trong cPickle đây là các hàm, không phải các lớp. Hầu hết các ứng dụng đều không cần chức năng này và có thể hưởng lợi từ hiệu suất được cải thiện của cPickle. Ngoài ra, các giao diện của hai mô-đun gần giống nhau; giao diện chung được mô tả trong sách hướng dẫn này và các khác biệt được chỉ ra khi cần thiết. Trong các cuộc thảo luận sau, chúng tôi sử dụng thuật ngữ “dưa chua” để mô tả chung mô đun dưa chuột và cPickle.

Luồng dữ liệu hai mô-đun sản xuất được đảm bảo có thể hoán đổi cho nhau.

+0

Đảm bảo luôn luôn mở các tệp dưa được tạo bằng giao thức> = 1 ở chế độ nhị phân. Đối với giao thức pickle dựa trên ASCII cũ, bạn có thể sử dụng chế độ văn bản hoặc chế độ nhị phân, miễn là bạn duy trì tính nhất quán. Một tệp dưa được viết bằng giao thức 0 ở chế độ nhị phân sẽ chứa các dòng đơn lẻ như các công cụ dòng và do đó sẽ trông “buồn cười” khi được xem trong Notepad hoặc các trình chỉnh sửa khác không hỗ trợ định dạng này. – Naren

+1

cpickle được chuyển thành _pickle trong python 3 – Naren

+0

cpickle nhanh hơn rất nhiều so với dưa chuột vì tên cho thấy nó được viết bằng ngôn ngữ c. – Naren

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