Python lưu đối tượng vào tệp nhị phân
Tôi khuyên bạn không nên dưa chua vì những lý do dễ dàng với Google. Nếu là tôi, có lẽ tôi chỉ cần thêm một phương thức vào lớp của mình có tên là toJson và có một hàm để tạo lớp từ JSON đó. Bạn cũng có thể xem xét jsonpickle Show
Hồi đáp Trang web Tìm Hồi đáp Exsul1 Bài đăng. 17 Chủ đề. 7 Đã tham gia. Tháng 9 năm 2019 Danh tiếng. 0 14-09-2019, 01. 04 giờ sángĐiều này có vẻ phức tạp không cần thiết đối với một thứ có vẻ đơn giản như lưu trữ dữ liệu. Mọi người thường làm như thế nào? Mô-đun thực hiện các giao thức nhị phân để tuần tự hóa và hủy tuần tự hóa cấu trúc đối tượng Python. “Pickling” là quá trình theo đó hệ thống phân cấp đối tượng Python được chuyển đổi thành luồng byte và “unpickling” là thao tác nghịch đảo, theo đó luồng byte (từ a hoặc ) được chuyển đổi trở lại thành hệ thống phân cấp đối tượng. Pickling (và unpickling) còn được gọi là “serialization”, “marshalling” hoặc “flattening”; Cảnh báo Mô-đun def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj7 không an toàn. Chỉ giải nén dữ liệu mà bạn tin tưởng Có thể xây dựng dữ liệu dưa chua độc hại sẽ thực thi mã tùy ý trong quá trình giải nén. Không bao giờ giải nén dữ liệu có thể đến từ một nguồn không đáng tin cậy hoặc có thể đã bị giả mạo Cân nhắc việc ký dữ liệu nếu bạn cần đảm bảo rằng dữ liệu không bị giả mạo Các định dạng tuần tự hóa an toàn hơn như có thể phù hợp hơn nếu bạn đang xử lý dữ liệu không đáng tin cậy. Nhìn thấy Mối quan hệ với các mô-đun Python khácSo sánh với # Simple example presenting how persistent ID can be used to pickle # external objects by reference. import pickle import sqlite3 from collections import namedtuple # Simple class representing a record in our database. MemoRecord = namedtuple("MemoRecord", "key, task") class DBPickler(pickle.Pickler): def persistent_id(self, obj): # Instead of pickling MemoRecord as a regular class instance, we emit a # persistent ID. if isinstance(obj, MemoRecord): # Here, our persistent ID is simply a tuple, containing a tag and a # key, which refers to a specific record in the database. return ("MemoRecord", obj.key) else: # If obj does not have a persistent ID, return None. This means obj # needs to be pickled as usual. return None class DBUnpickler(pickle.Unpickler): def __init__(self, file, connection): super().__init__(file) self.connection = connection def persistent_load(self, pid): # This method is invoked whenever a persistent ID is encountered. # Here, pid is the tuple returned by DBPickler. cursor = self.connection.cursor() type_tag, key_id = pid if type_tag == "MemoRecord": # Fetch the referenced record from the database and return it. cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),)) key, task = cursor.fetchone() return MemoRecord(key, task) else: # Always raises an error if you cannot return the correct object. # Otherwise, the unpickler will think None is the object referenced # by the persistent ID. raise pickle.UnpicklingError("unsupported persistent object") def main(): import io import pprint # Initialize and populate our database. conn = sqlite3.connect(":memory:") cursor = conn.cursor() cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)") tasks = ( 'give food to fish', 'prepare group meeting', 'fight with a zebra', ) for task in tasks: cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,)) # Fetch the records to be pickled. cursor.execute("SELECT * FROM memos") memos = [MemoRecord(key, task) for key, task in cursor] # Save the records using our custom DBPickler. file = io.BytesIO() DBPickler(file).dump(memos) print("Pickled records:") pprint.pprint(memos) # Update a record, just for good measure. cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1") # Load the records from the pickle data stream. file.seek(0) memos = DBUnpickler(file, conn).load() print("Unpickled records:") pprint.pprint(memos) if __name__ == '__main__': main() 2Python có một mô-đun tuần tự hóa nguyên thủy hơn được gọi là , nhưng nói chung phải luôn là cách ưu tiên để tuần tự hóa các đối tượng Python. tồn tại chủ yếu để hỗ trợ các tệp # Simple example presenting how persistent ID can be used to pickle # external objects by reference. import pickle import sqlite3 from collections import namedtuple # Simple class representing a record in our database. MemoRecord = namedtuple("MemoRecord", "key, task") class DBPickler(pickle.Pickler): def persistent_id(self, obj): # Instead of pickling MemoRecord as a regular class instance, we emit a # persistent ID. if isinstance(obj, MemoRecord): # Here, our persistent ID is simply a tuple, containing a tag and a # key, which refers to a specific record in the database. return ("MemoRecord", obj.key) else: # If obj does not have a persistent ID, return None. This means obj # needs to be pickled as usual. return None class DBUnpickler(pickle.Unpickler): def __init__(self, file, connection): super().__init__(file) self.connection = connection def persistent_load(self, pid): # This method is invoked whenever a persistent ID is encountered. # Here, pid is the tuple returned by DBPickler. cursor = self.connection.cursor() type_tag, key_id = pid if type_tag == "MemoRecord": # Fetch the referenced record from the database and return it. cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),)) key, task = cursor.fetchone() return MemoRecord(key, task) else: # Always raises an error if you cannot return the correct object. # Otherwise, the unpickler will think None is the object referenced # by the persistent ID. raise pickle.UnpicklingError("unsupported persistent object") def main(): import io import pprint # Initialize and populate our database. conn = sqlite3.connect(":memory:") cursor = conn.cursor() cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)") tasks = ( 'give food to fish', 'prepare group meeting', 'fight with a zebra', ) for task in tasks: cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,)) # Fetch the records to be pickled. cursor.execute("SELECT * FROM memos") memos = [MemoRecord(key, task) for key, task in cursor] # Save the records using our custom DBPickler. file = io.BytesIO() DBPickler(file).dump(memos) print("Pickled records:") pprint.pprint(memos) # Update a record, just for good measure. cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1") # Load the records from the pickle data stream. file.seek(0) memos = DBUnpickler(file, conn).load() print("Unpickled records:") pprint.pprint(memos) if __name__ == '__main__': main()6 của Python Mô-đun khác với một số cách quan trọng
So sánh với # Simple example presenting how persistent ID can be used to pickle # external objects by reference. import pickle import sqlite3 from collections import namedtuple # Simple class representing a record in our database. MemoRecord = namedtuple("MemoRecord", "key, task") class DBPickler(pickle.Pickler): def persistent_id(self, obj): # Instead of pickling MemoRecord as a regular class instance, we emit a # persistent ID. if isinstance(obj, MemoRecord): # Here, our persistent ID is simply a tuple, containing a tag and a # key, which refers to a specific record in the database. return ("MemoRecord", obj.key) else: # If obj does not have a persistent ID, return None. This means obj # needs to be pickled as usual. return None class DBUnpickler(pickle.Unpickler): def __init__(self, file, connection): super().__init__(file) self.connection = connection def persistent_load(self, pid): # This method is invoked whenever a persistent ID is encountered. # Here, pid is the tuple returned by DBPickler. cursor = self.connection.cursor() type_tag, key_id = pid if type_tag == "MemoRecord": # Fetch the referenced record from the database and return it. cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),)) key, task = cursor.fetchone() return MemoRecord(key, task) else: # Always raises an error if you cannot return the correct object. # Otherwise, the unpickler will think None is the object referenced # by the persistent ID. raise pickle.UnpicklingError("unsupported persistent object") def main(): import io import pprint # Initialize and populate our database. conn = sqlite3.connect(":memory:") cursor = conn.cursor() cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)") tasks = ( 'give food to fish', 'prepare group meeting', 'fight with a zebra', ) for task in tasks: cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,)) # Fetch the records to be pickled. cursor.execute("SELECT * FROM memos") memos = [MemoRecord(key, task) for key, task in cursor] # Save the records using our custom DBPickler. file = io.BytesIO() DBPickler(file).dump(memos) print("Pickled records:") pprint.pprint(memos) # Update a record, just for good measure. cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1") # Load the records from the pickle data stream. file.seek(0) memos = DBUnpickler(file, conn).load() print("Unpickled records:") pprint.pprint(memos) if __name__ == '__main__': main() 1Có sự khác biệt cơ bản giữa các giao thức pickle và JSON (Ký hiệu đối tượng JavaScript)
Xem thêm mô-đun. một mô-đun thư viện tiêu chuẩn cho phép tuần tự hóa và giải tuần tự hóa JSON Định dạng luồng dữ liệuĐịnh dạng dữ liệu được sử dụng là dành riêng cho Python. Điều này có lợi thế là không có hạn chế nào được áp đặt bởi các tiêu chuẩn bên ngoài như JSON hoặc XDR (không thể đại diện cho việc chia sẻ con trỏ); Theo mặc định, định dạng dữ liệu sử dụng biểu diễn nhị phân tương đối nhỏ gọn. Nếu cần các đặc điểm kích thước tối ưu, bạn có thể nén dữ liệu được chọn một cách hiệu quả. Mô-đun chứa các công cụ để phân tích các luồng dữ liệu được tạo bởi. mã nguồn có nhiều nhận xét về opcode được sử dụng bởi các giao thức pickle Hiện tại có 6 giao thức khác nhau có thể được sử dụng để tẩy. Giao thức được sử dụng càng cao thì phiên bản Python cần thiết để đọc dưa chua được tạo ra càng mới
Ghi chú Tuần tự hóa là một khái niệm nguyên thủy hơn là kiên trì; . Mô-đun có thể chuyển đổi một đối tượng phức tạp thành luồng byte và nó có thể chuyển đổi luồng byte thành một đối tượng có cùng cấu trúc bên trong. Có lẽ điều rõ ràng nhất cần làm với các luồng byte này là ghi chúng vào một tệp, nhưng cũng có thể gửi chúng qua mạng hoặc lưu trữ chúng trong cơ sở dữ liệu. Mô-đun này cung cấp một giao diện đơn giản để chọn và bỏ chọn các đối tượng trên các tệp cơ sở dữ liệu kiểu DBM Giao diện mô-đunĐể tuần tự hóa một hệ thống phân cấp đối tượng, bạn chỉ cần gọi hàm. Tương tự, để hủy tuần tự hóa luồng dữ liệu, bạn gọi hàm. Tuy nhiên, nếu bạn muốn kiểm soát nhiều hơn đối với tuần tự hóa và hủy tuần tự hóa, bạn có thể tạo một hoặc một đối tượng tương ứng Mô-đun cung cấp các hằng số sau dưa chua. HIGHEST_PROTOCOLMột số nguyên, cao nhất hiện có. Giá trị này có thể được chuyển dưới dạng giá trị giao thức cho các hàm và cũng như hàm tạo dưa chua. DEFAULT_PROTOCOLMột số nguyên, mặc định được sử dụng để tẩy. Có thể ít hơn. Hiện tại giao thức mặc định là 4, được giới thiệu lần đầu trong Python 3. 4 và không tương thích với các phiên bản trước Đã thay đổi trong phiên bản 3. 0. Giao thức mặc định là 3. Đã thay đổi trong phiên bản 3. 8. Giao thức mặc định là 4. Mô-đun cung cấp các chức năng sau để làm cho quá trình ngâm thuận tiện hơn dưa chua. kết xuất(obj , tệp, protocol=None, *, fix_imports=True, buffer_callback=None)Viết biểu diễn ngâm của đối tượng obj vào tệp đang mở. Điều này tương đương với copyreg.pickle(SomeClass, reduce_SomeClass) f = io.BytesIO() p = pickle.Pickler(f)9 Tệp đối số, giao thức, fix_imports và buffer_callback có cùng ý nghĩa như trong hàm tạo Đã thay đổi trong phiên bản 3. 8. Đã thêm đối số buffer_callback. dưa chua. kết xuất(obj , giao thức=None, *, fix_imports=True, buffer_callback=None)Trả lại biểu diễn đã chọn của đối tượng obj dưới dạng một đối tượng, thay vì ghi nó vào một tệp Giao thức đối số, fix_imports và buffer_callback có cùng ý nghĩa như trong hàm tạo Đã thay đổi trong phiên bản 3. 8. Đã thêm đối số buffer_callback. dưa chua. tải(tệp , *, fix_imports=True, encoding='ASCII', errors='strict', buffers=None)Đọc biểu diễn được chọn của một đối tượng từ tệp đang mở và trả về cấu trúc phân cấp đối tượng được hoàn nguyên được chỉ định trong đó. Điều này tương đương với class TextReader: """Print and number lines in a text file.""" def __init__(self, filename): self.filename = filename self.file = open(filename) self.lineno = 0 def readline(self): self.lineno += 1 line = self.file.readline() if not line: return None if line.endswith('\n'): line = line[:-1] return "%i: %s" % (self.lineno, line) def __getstate__(self): # Copy the object's state from self.__dict__ which contains # all our instance attributes. Always use the dict.copy() # method to avoid modifying the original state. state = self.__dict__.copy() # Remove the unpicklable entries. del state['file'] return state def __setstate__(self, state): # Restore instance attributes (i.e., filename and lineno). self.__dict__.update(state) # Restore the previously opened file's state. To do so, we need to # reopen it and read from it until the line count is restored. file = open(self.filename) for _ in range(self.lineno): file.readline() # Finally, save the file. self.file = file3 Phiên bản giao thức của dưa chua được phát hiện tự động, vì vậy không cần đối số giao thức. Các byte vượt qua biểu diễn ngâm của đối tượng bị bỏ qua Tệp đối số, fix_imports, mã hóa, lỗi, nghiêm ngặt và bộ đệm có cùng ý nghĩa như trong hàm tạo Đã thay đổi trong phiên bản 3. 8. Đã thêm đối số bộ đệm. dưa chua. tải(dữ liệu , /, *, fix_imports=True, encoding='ASCII', errors='strict', buffers=None)Trả về cấu trúc phân cấp đối tượng được hoàn nguyên của dữ liệu đại diện đã chọn của một đối tượng. dữ liệu phải là một Phiên bản giao thức của dưa chua được phát hiện tự động, vì vậy không cần đối số giao thức. Các byte vượt qua biểu diễn ngâm của đối tượng bị bỏ qua Các đối số fix_imports, mã hóa, lỗi, nghiêm ngặt và bộ đệm có cùng ý nghĩa như trong hàm tạo Đã thay đổi trong phiên bản 3. 8. Đã thêm đối số bộ đệm. Mô-đun xác định ba trường hợp ngoại lệ ngoại lệ dưa chua. Lỗi dưa chuaLớp cơ sở chung cho các ngoại lệ tẩy khác. Nó kế thừa ngoại lệ dưa chua. Lỗi tẩyLỗi xuất hiện khi một đối tượng không thể chọn được gặp phải bởi. Nó kế thừa Tham khảo để biết những loại đồ vật nào có thể ngâm được ngoại lệ dưa chua. Lỗi bỏ chọnLỗi xuất hiện khi có sự cố khi giải nén một đối tượng, chẳng hạn như hỏng dữ liệu hoặc vi phạm bảo mật. Nó kế thừa Lưu ý rằng các ngoại lệ khác cũng có thể được nêu ra trong quá trình bỏ chọn, bao gồm (nhưng không nhất thiết giới hạn ở) AttributeError, EOFError, ImportError và IndexError Mô-đun xuất ba lớp, và lớp dưa chua. Pickler(tệp , giao thức=None, *, fix_imports=True, buffer_callback=None)Điều này cần một tệp nhị phân để ghi luồng dữ liệu dưa chua Đối số giao thức tùy chọn, một số nguyên, báo cho bộ chọn sử dụng giao thức đã cho; . Nếu không được chỉ định, mặc định là. Nếu một số âm được chỉ định, được chọn Đối số tệp phải có phương thức write() chấp nhận một đối số byte đơn. Do đó, nó có thể là một tệp trên đĩa được mở để ghi nhị phân, một thể hiện hoặc bất kỳ đối tượng tùy chỉnh nào khác đáp ứng giao diện này Nếu fix_imports là true và giao thức nhỏ hơn 3, pickle sẽ cố gắng ánh xạ tên Python 3 mới sang tên mô-đun cũ được sử dụng trong Python 2, để có thể đọc được luồng dữ liệu pickle bằng Python 2 Nếu buffer_callback là Không có (mặc định), chế độ xem bộ đệm được tuần tự hóa thành tệp như một phần của luồng pickle Nếu buffer_callback không phải là Không, thì nó có thể được gọi bất kỳ số lần nào với chế độ xem bộ đệm. Nếu cuộc gọi lại trả về một giá trị sai (chẳng hạn như Không), bộ đệm đã cho là; . e. bên trong dòng dưa chua Đó là lỗi nếu buffer_callback không phải là Không có và giao thức là Không có hoặc nhỏ hơn 5 Đã thay đổi trong phiên bản 3. 8. Đã thêm đối số buffer_callback. kết xuất(obj)Viết biểu diễn được chọn của obj vào đối tượng tệp đang mở được cung cấp trong hàm tạo persistent_id(obj)Không làm gì theo mặc định. Điều này tồn tại để một lớp con có thể ghi đè lên nó Nếu trả về import io import pickle class MyClass: my_attribute = 1 class MyPickler(pickle.Pickler): def reducer_override(self, obj): """Custom reducer for MyClass.""" if getattr(obj, "__name__", None) == "MyClass": return type, (obj.__name__, obj.__bases__, {'my_attribute': obj.my_attribute}) else: # For any other object, fallback to usual reduction return NotImplemented f = io.BytesIO() p = MyPickler(f) p.dump(MyClass) del MyClass unpickled_class = pickle.loads(f.getvalue()) assert isinstance(unpickled_class, type) assert unpickled_class.__name__ == "MyClass" assert unpickled_class.my_attribute == 10, obj được ngâm như bình thường. Bất kỳ giá trị nào khác sẽ tạo ra giá trị được trả về dưới dạng ID liên tục cho obj. Ý nghĩa của ID liên tục này phải được xác định bởi. Lưu ý rằng giá trị được trả về không thể có ID cố định Xem để biết chi tiết và ví dụ về cách sử dụng công văn_tableBảng điều phối của đối tượng bộ chọn là sổ đăng ký các hàm rút gọn thuộc loại có thể được khai báo bằng cách sử dụng. Nó là một ánh xạ có khóa là các lớp và có giá trị là các hàm rút gọn. Một hàm rút gọn nhận một đối số duy nhất của lớp được liên kết và phải tuân theo cùng một giao diện như một phương thức import io import pickle class MyClass: my_attribute = 1 class MyPickler(pickle.Pickler): def reducer_override(self, obj): """Custom reducer for MyClass.""" if getattr(obj, "__name__", None) == "MyClass": return type, (obj.__name__, obj.__bases__, {'my_attribute': obj.my_attribute}) else: # For any other object, fallback to usual reduction return NotImplemented f = io.BytesIO() p = MyPickler(f) p.dump(MyClass) del MyClass unpickled_class = pickle.loads(f.getvalue()) assert isinstance(unpickled_class, type) assert unpickled_class.__name__ == "MyClass" assert unpickled_class.my_attribute == 15 Theo mặc định, một đối tượng bộ chọn sẽ không có thuộc tính và thay vào đó, nó sẽ sử dụng bảng điều phối chung do mô-đun quản lý. Tuy nhiên, để tùy chỉnh phần tẩy cho một đối tượng bộ chọn cụ thể, người ta có thể đặt thuộc tính thành một đối tượng giống như dict. Ngoài ra, nếu một lớp con của có thuộc tính thì thuộc tính này sẽ được sử dụng làm bảng điều phối mặc định cho các thể hiện của lớp đó Xem các ví dụ sử dụng Mới trong phiên bản 3. 3 reducer_override(obj)Bộ giảm tốc đặc biệt có thể được định nghĩa trong các lớp con. Phương pháp này được ưu tiên hơn bất kỳ bộ giảm tốc nào trong. Nó phải phù hợp với cùng một giao diện như một phương pháp import io import pickle class MyClass: my_attribute = 1 class MyPickler(pickle.Pickler): def reducer_override(self, obj): """Custom reducer for MyClass.""" if getattr(obj, "__name__", None) == "MyClass": return type, (obj.__name__, obj.__bases__, {'my_attribute': obj.my_attribute}) else: # For any other object, fallback to usual reduction return NotImplemented f = io.BytesIO() p = MyPickler(f) p.dump(MyClass) del MyClass unpickled_class = pickle.loads(f.getvalue()) assert isinstance(unpickled_class, type) assert unpickled_class.__name__ == "MyClass" assert unpickled_class.my_attribute == 15 và có thể tùy ý trả lại class ZeroCopyByteArray(bytearray): def __reduce_ex__(self, protocol): if protocol >= 5: return type(self)._reconstruct, (PickleBuffer(self),), None else: # PickleBuffer is forbidden with pickle protocols <= 4. return type(self)._reconstruct, (bytearray(self),) @classmethod def _reconstruct(cls, obj): with memoryview(obj) as m: # Get a handle over the original buffer object obj = m.obj if type(obj) is cls: # Original buffer object is a ZeroCopyByteArray, return it # as-is. return obj else: return cls(obj)4 để dự phòng trên các bộ giảm tốc đã đăng ký thành dưa chua class ZeroCopyByteArray(bytearray): def __reduce_ex__(self, protocol): if protocol >= 5: return type(self)._reconstruct, (PickleBuffer(self),), None else: # PickleBuffer is forbidden with pickle protocols <= 4. return type(self)._reconstruct, (bytearray(self),) @classmethod def _reconstruct(cls, obj): with memoryview(obj) as m: # Get a handle over the original buffer object obj = m.obj if type(obj) is cls: # Original buffer object is a ZeroCopyByteArray, return it # as-is. return obj else: return cls(obj)6 Đối với một ví dụ chi tiết, xem Mới trong phiên bản 3. 8 nhanhkhông dùng nữa. Bật chế độ nhanh nếu được đặt thành giá trị thực. Chế độ nhanh vô hiệu hóa việc sử dụng ghi nhớ, do đó tăng tốc quá trình tẩy bằng cách không tạo mã PUT thừa. Nó không nên được sử dụng với các đối tượng tự tham chiếu, nếu không sẽ gây ra sự lặp lại vô hạn Sử dụng nếu bạn cần dưa chua nhỏ gọn hơn lớp dưa chua. Trình giải nén(tệp , *, fix_imports=True, encoding='ASCII', errors='strict', buffers=None)Điều này cần một tệp nhị phân để đọc luồng dữ liệu dưa chua Phiên bản giao thức của dưa chua được phát hiện tự động, vì vậy không cần đối số giao thức Tệp đối số phải có ba phương thức, phương thức read() nhận đối số số nguyên, phương thức readinto() nhận đối số bộ đệm và phương thức readline() không yêu cầu đối số, như trong giao diện. Do đó, tệp có thể là tệp trên đĩa được mở để đọc nhị phân, đối tượng hoặc bất kỳ đối tượng tùy chỉnh nào khác đáp ứng giao diện này Các đối số tùy chọn fix_imports, mã hóa và lỗi được sử dụng để kiểm soát hỗ trợ tương thích cho luồng dưa chua do Python 2 tạo ra. Nếu fix_imports là true, pickle sẽ cố ánh xạ tên cũ của Python 2 sang tên mới được sử dụng trong Python 3. Mã hóa và lỗi cho pickle biết cách giải mã các trường hợp chuỗi 8 bit được chọn bởi Python 2; . Mã hóa có thể là 'byte' để đọc các trường hợp chuỗi 8 bit này dưới dạng các đối tượng byte. Cần sử dụng def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj01 để bỏ chọn các mảng NumPy và các phiên bản của , và được chọn bởi Python 2 Nếu bộ đệm là Không có (mặc định), thì tất cả dữ liệu cần thiết cho quá trình khử lưu huỳnh phải được chứa trong luồng dưa chua. Điều này có nghĩa là đối số buffer_callback là Không có khi a được khởi tạo (hoặc khi hoặc được gọi) Nếu bộ đệm không phải là Không, thì nó phải là một đối tượng kích hoạt bộ đệm có thể lặp lại được sử dụng mỗi khi luồng dưa chua tham chiếu chế độ xem bộ đệm. Các bộ đệm như vậy đã được cung cấp theo thứ tự buffer_callback của đối tượng Pickler Đã thay đổi trong phiên bản 3. 8. Đã thêm đối số bộ đệm. tải()Đọc biểu diễn được chọn của một đối tượng từ đối tượng tệp mở được cung cấp trong hàm tạo và trả về cấu trúc phân cấp đối tượng được hoàn nguyên được chỉ định trong đó. Các byte vượt qua biểu diễn ngâm của đối tượng bị bỏ qua persistent_load(pid)Tăng một theo mặc định Nếu được xác định, sẽ trả về đối tượng được chỉ định bởi pid ID liên tục. Nếu gặp phải một ID liên tục không hợp lệ, nên tăng Xem để biết chi tiết và ví dụ về cách sử dụng find_class(mô-đun , tên)Nhập mô-đun nếu cần và trả về đối tượng được gọi là tên từ nó, trong đó các đối số mô-đun và tên là các đối tượng. Lưu ý, không giống như tên gọi của nó, cũng được sử dụng để tìm các chức năng Các lớp con có thể ghi đè điều này để giành quyền kiểm soát loại đối tượng nào và cách chúng có thể được tải, có khả năng giảm rủi ro bảo mật. Tham khảo để biết chi tiết Đưa ra một def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj13 với các đối số def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj14, def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj15lớp dưa chua. Bộ đệm dưa chua(bộ đệm) Trình bao bọc cho bộ đệm đại diện cho dữ liệu có thể chọn. bộ đệm phải là một đối tượng, chẳng hạn như một hoặc một mảng N chiều bản thân nó là một nhà cung cấp bộ đệm, do đó có thể chuyển nó tới các API khác mong đợi một đối tượng cung cấp bộ đệm, chẳng hạn như các đối tượng chỉ có thể được sắp xếp theo thứ tự bằng cách sử dụng giao thức pickle 5 trở lên. Họ đủ điều kiện cho Mới trong phiên bản 3. 8 thô()Trả về một vùng bộ nhớ bên dưới bộ đệm này. Đối tượng được trả về là một chế độ xem bộ nhớ liền kề C, một chiều với định dạng def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj20 (byte không dấu). được nâng lên nếu bộ đệm không phải là C- hoặc Fortran-tiếp giápphát hành() Giải phóng bộ đệm cơ bản được hiển thị bởi đối tượng PickleBuffer Những gì có thể được ngâm và bỏ?Các loại sau đây có thể được ngâm
Cố gắng chọn các đối tượng không thể chọn sẽ làm tăng ngoại lệ; . Cố gắng chọn cấu trúc dữ liệu có tính đệ quy cao có thể vượt quá độ sâu đệ quy tối đa, a sẽ được nêu ra trong trường hợp này. Bạn có thể cẩn thận tăng giới hạn này với Lưu ý rằng các chức năng (được tích hợp sẵn và do người dùng xác định) được chọn đầy đủ chứ không phải theo giá trị. Điều này có nghĩa là chỉ có tên hàm được chọn, cùng với tên của mô-đun chứa và các lớp. Cả mã của chức năng cũng như bất kỳ thuộc tính chức năng nào của nó đều không được chọn. Do đó, mô-đun xác định phải có thể nhập được trong môi trường giải nén và mô-đun phải chứa đối tượng được đặt tên, nếu không một ngoại lệ sẽ được đưa ra. Tương tự, các lớp được chọn theo tên đủ điều kiện, do đó, các hạn chế tương tự trong môi trường bỏ chọn được áp dụng. Lưu ý rằng không có mã hoặc dữ liệu nào của lớp được chọn, vì vậy trong ví dụ sau, thuộc tính lớp def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj31 không được khôi phục trong môi trường không được chọn class Foo: attr = 'A class attribute' picklestring = pickle.dumps(Foo) Những hạn chế này là lý do tại sao các hàm và lớp có thể chọn phải được xác định ở cấp cao nhất của mô-đun Tương tự, khi các thể hiện của lớp được chọn, mã và dữ liệu của lớp không được chọn cùng với chúng. Chỉ dữ liệu cá thể được chọn. Điều này được thực hiện có mục đích, vì vậy bạn có thể sửa lỗi trong một lớp hoặc thêm các phương thức vào lớp và vẫn tải các đối tượng đã được tạo bằng phiên bản cũ hơn của lớp. Nếu bạn dự định có các đối tượng tồn tại lâu dài sẽ thấy nhiều phiên bản của một lớp, thì có thể đáng để đặt số phiên bản vào các đối tượng để có thể thực hiện các chuyển đổi phù hợp bằng phương thức def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj32 của lớp Phiên bản lớp PicklingTrong phần này, chúng tôi mô tả các cơ chế chung có sẵn để bạn xác định, tùy chỉnh và kiểm soát cách các thể hiện của lớp được chọn và bỏ chọn Trong hầu hết các trường hợp, không cần mã bổ sung để làm cho các phiên bản có thể chọn được. Theo mặc định, pickle sẽ truy xuất lớp và các thuộc tính của một cá thể thông qua nội quan. Khi một thể hiện của lớp không được chọn, phương thức def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj33 của nó thường không được gọi. Hành vi mặc định trước tiên tạo một phiên bản chưa được khởi tạo, sau đó khôi phục các thuộc tính đã lưu. Đoạn mã sau đây cho thấy việc thực hiện hành vi này def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj Các lớp có thể thay đổi hành vi mặc định bằng cách cung cấp một hoặc một số phương thức đặc biệt đối tượng. __getnewargs_ex__()Trong các giao thức 2 trở lên, các lớp triển khai phương thức có thể ra lệnh cho các giá trị được truyền cho phương thức khi giải nén. Phương thức phải trả về một cặp def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj36 trong đó args là một bộ các đối số vị trí và kwargs là một từ điển các đối số được đặt tên để xây dựng đối tượng. Chúng sẽ được chuyển đến phương thức khi giải nén Bạn nên triển khai phương thức này nếu phương thức của lớp bạn yêu cầu các đối số chỉ có từ khóa. Mặt khác, nó được khuyến nghị để tương thích để thực hiện Đã thay đổi trong phiên bản 3. 6. hiện được sử dụng trong giao thức 2 và 3. đối tượng. __getnewargs__()Phương thức này phục vụ mục đích tương tự như , nhưng chỉ hỗ trợ các đối số vị trí. Nó phải trả về một bộ đối số def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj42 sẽ được truyền cho phương thức khi giải nén sẽ không được gọi nếu được xác định Đã thay đổi trong phiên bản 3. 6. Trước Python 3. 6, được gọi thay vì trong giao thức 2 và 3. đối tượng. __getstate__()Các lớp có thể ảnh hưởng hơn nữa đến cách các thể hiện của chúng được chọn bằng cách ghi đè phương thức. Nó được gọi và đối tượng được trả về được chọn làm nội dung cho thể hiện, thay vì trạng thái mặc định. Có một số trường hợp
Đã thay đổi trong phiên bản 3. 11. Đã thêm cài đặt mặc định của phương thức def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj27 trong lớp. đối tượng. __setstate__(trạng thái) Khi unpickling, nếu lớp định nghĩa, nó được gọi với trạng thái unpickled. Trong trường hợp đó, không có yêu cầu đối với đối tượng trạng thái là một từ điển. Mặt khác, trạng thái được chọn phải là một từ điển và các mục của nó được gán cho từ điển của phiên bản mới Ghi chú Nếu trả về một giá trị sai, phương thức sẽ không được gọi khi giải nén Tham khảo phần này để biết thêm thông tin về cách sử dụng các phương pháp def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj27 và def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj32 Ghi chú Tại thời điểm giải nén, một số phương thức như def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj68, def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj69 hoặc def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj70 có thể được gọi trong trường hợp. Trong trường hợp các phương thức đó dựa vào một số bất biến bên trong là đúng, thì loại đó nên triển khai def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj35 để thiết lập một bất biến như vậy, vì def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj33 không được gọi khi giải nén một thể hiện Như chúng ta sẽ thấy, dưa chua không sử dụng trực tiếp các phương pháp được mô tả ở trên. Trên thực tế, các phương thức này là một phần của giao thức sao chép thực hiện phương thức đặc biệt import io import pickle class MyClass: my_attribute = 1 class MyPickler(pickle.Pickler): def reducer_override(self, obj): """Custom reducer for MyClass.""" if getattr(obj, "__name__", None) == "MyClass": return type, (obj.__name__, obj.__bases__, {'my_attribute': obj.my_attribute}) else: # For any other object, fallback to usual reduction return NotImplemented f = io.BytesIO() p = MyPickler(f) p.dump(MyClass) del MyClass unpickled_class = pickle.loads(f.getvalue()) assert isinstance(unpickled_class, type) assert unpickled_class.__name__ == "MyClass" assert unpickled_class.my_attribute == 15. Giao thức sao chép cung cấp một giao diện thống nhất để truy xuất dữ liệu cần thiết cho việc chọn lọc và sao chép các đối tượng. Mặc dù mạnh mẽ, nhưng việc triển khai import io import pickle class MyClass: my_attribute = 1 class MyPickler(pickle.Pickler): def reducer_override(self, obj): """Custom reducer for MyClass.""" if getattr(obj, "__name__", None) == "MyClass": return type, (obj.__name__, obj.__bases__, {'my_attribute': obj.my_attribute}) else: # For any other object, fallback to usual reduction return NotImplemented f = io.BytesIO() p = MyPickler(f) p.dump(MyClass) del MyClass unpickled_class = pickle.loads(f.getvalue()) assert isinstance(unpickled_class, type) assert unpickled_class.__name__ == "MyClass" assert unpickled_class.my_attribute == 15 trực tiếp trong các lớp học của bạn rất dễ xảy ra lỗi. Vì lý do này, các nhà thiết kế lớp nên sử dụng giao diện cấp cao (i. e. , def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj34, def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj27 và def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj32) bất cứ khi nào có thể. Tuy nhiên, chúng tôi sẽ chỉ ra các trường hợp sử dụng import io import pickle class MyClass: my_attribute = 1 class MyPickler(pickle.Pickler): def reducer_override(self, obj): """Custom reducer for MyClass.""" if getattr(obj, "__name__", None) == "MyClass": return type, (obj.__name__, obj.__bases__, {'my_attribute': obj.my_attribute}) else: # For any other object, fallback to usual reduction return NotImplemented f = io.BytesIO() p = MyPickler(f) p.dump(MyClass) del MyClass unpickled_class = pickle.loads(f.getvalue()) assert isinstance(unpickled_class, type) assert unpickled_class.__name__ == "MyClass" assert unpickled_class.my_attribute == 15 là lựa chọn duy nhất hoặc dẫn đến việc ngâm chua hiệu quả hơn hoặc cả haiđối tượng. __reduce__() Giao diện hiện được định nghĩa như sau. Phương thức này không có đối số và sẽ trả về một chuỗi hoặc tốt nhất là một bộ dữ liệu (đối tượng được trả về thường được gọi là “giá trị rút gọn”) Nếu một chuỗi được trả về, chuỗi đó sẽ được hiểu là tên của một biến toàn cục. Nó phải là tên địa phương của đối tượng liên quan đến mô-đun của nó; . Hành vi này thường hữu ích cho người độc thân Khi một bộ dữ liệu được trả về, nó phải dài từ hai đến sáu phần tử. Các mục tùy chọn có thể được bỏ qua hoặc có thể cung cấp import io import pickle class MyClass: my_attribute = 1 class MyPickler(pickle.Pickler): def reducer_override(self, obj): """Custom reducer for MyClass.""" if getattr(obj, "__name__", None) == "MyClass": return type, (obj.__name__, obj.__bases__, {'my_attribute': obj.my_attribute}) else: # For any other object, fallback to usual reduction return NotImplemented f = io.BytesIO() p = MyPickler(f) p.dump(MyClass) del MyClass unpickled_class = pickle.loads(f.getvalue()) assert isinstance(unpickled_class, type) assert unpickled_class.__name__ == "MyClass" assert unpickled_class.my_attribute == 10 làm giá trị của chúng. Ngữ nghĩa của từng mục theo thứ tự
Ngoài ra, một phương pháp có thể được xác định. Sự khác biệt duy nhất là phương thức này sẽ nhận một đối số nguyên duy nhất, phiên bản giao thức. Khi được xác định, pickle sẽ thích nó hơn phương thức. Ngoài ra, tự động trở thành từ đồng nghĩa với phiên bản mở rộng. Công dụng chính của phương pháp này là cung cấp các giá trị giảm tương thích ngược cho các bản phát hành Python cũ hơn Sự bền bỉ của các đối tượng bên ngoàiVì lợi ích của tính bền vững của đối tượng, mô-đun hỗ trợ khái niệm tham chiếu đến một đối tượng bên ngoài luồng dữ liệu được chọn. Các đối tượng như vậy được tham chiếu bởi một ID cố định, ID này phải là một chuỗi ký tự chữ và số (đối với giao thức 0) hoặc chỉ là một đối tượng tùy ý (đối với bất kỳ giao thức mới nào) Độ phân giải của các ID liên tục như vậy không được xác định bởi mô-đun; Để chọn các đối tượng có ID cố định bên ngoài, trình chọn phải có một phương thức tùy chỉnh lấy một đối tượng làm đối số và trả về import io import pickle class MyClass: my_attribute = 1 class MyPickler(pickle.Pickler): def reducer_override(self, obj): """Custom reducer for MyClass.""" if getattr(obj, "__name__", None) == "MyClass": return type, (obj.__name__, obj.__bases__, {'my_attribute': obj.my_attribute}) else: # For any other object, fallback to usual reduction return NotImplemented f = io.BytesIO() p = MyPickler(f) p.dump(MyClass) del MyClass unpickled_class = pickle.loads(f.getvalue()) assert isinstance(unpickled_class, type) assert unpickled_class.__name__ == "MyClass" assert unpickled_class.my_attribute == 10 hoặc ID liên tục cho đối tượng đó. Khi import io import pickle class MyClass: my_attribute = 1 class MyPickler(pickle.Pickler): def reducer_override(self, obj): """Custom reducer for MyClass.""" if getattr(obj, "__name__", None) == "MyClass": return type, (obj.__name__, obj.__bases__, {'my_attribute': obj.my_attribute}) else: # For any other object, fallback to usual reduction return NotImplemented f = io.BytesIO() p = MyPickler(f) p.dump(MyClass) del MyClass unpickled_class = pickle.loads(f.getvalue()) assert isinstance(unpickled_class, type) assert unpickled_class.__name__ == "MyClass" assert unpickled_class.my_attribute == 10 được trả lại, người nhặt chỉ cần nhặt đồ vật như bình thường. Khi một chuỗi ID cố định được trả về, bộ chọn sẽ chọn đối tượng đó, cùng với một điểm đánh dấu để bộ giải nén sẽ nhận ra đó là một ID cố định Để bỏ chọn các đối tượng bên ngoài, trình giải nén phải có một phương thức tùy chỉnh nhận một đối tượng ID liên tục và trả về đối tượng được tham chiếu Dưới đây là một ví dụ toàn diện trình bày cách ID liên tục có thể được sử dụng để chọn các đối tượng bên ngoài bằng tham chiếu # Simple example presenting how persistent ID can be used to pickle # external objects by reference. import pickle import sqlite3 from collections import namedtuple # Simple class representing a record in our database. MemoRecord = namedtuple("MemoRecord", "key, task") class DBPickler(pickle.Pickler): def persistent_id(self, obj): # Instead of pickling MemoRecord as a regular class instance, we emit a # persistent ID. if isinstance(obj, MemoRecord): # Here, our persistent ID is simply a tuple, containing a tag and a # key, which refers to a specific record in the database. return ("MemoRecord", obj.key) else: # If obj does not have a persistent ID, return None. This means obj # needs to be pickled as usual. return None class DBUnpickler(pickle.Unpickler): def __init__(self, file, connection): super().__init__(file) self.connection = connection def persistent_load(self, pid): # This method is invoked whenever a persistent ID is encountered. # Here, pid is the tuple returned by DBPickler. cursor = self.connection.cursor() type_tag, key_id = pid if type_tag == "MemoRecord": # Fetch the referenced record from the database and return it. cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),)) key, task = cursor.fetchone() return MemoRecord(key, task) else: # Always raises an error if you cannot return the correct object. # Otherwise, the unpickler will think None is the object referenced # by the persistent ID. raise pickle.UnpicklingError("unsupported persistent object") def main(): import io import pprint # Initialize and populate our database. conn = sqlite3.connect(":memory:") cursor = conn.cursor() cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)") tasks = ( 'give food to fish', 'prepare group meeting', 'fight with a zebra', ) for task in tasks: cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,)) # Fetch the records to be pickled. cursor.execute("SELECT * FROM memos") memos = [MemoRecord(key, task) for key, task in cursor] # Save the records using our custom DBPickler. file = io.BytesIO() DBPickler(file).dump(memos) print("Pickled records:") pprint.pprint(memos) # Update a record, just for good measure. cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1") # Load the records from the pickle data stream. file.seek(0) memos = DBUnpickler(file, conn).load() print("Unpickled records:") pprint.pprint(memos) if __name__ == '__main__': main() Bảng công vănNếu một người muốn tùy chỉnh việc tẩy một số lớp mà không làm ảnh hưởng đến bất kỳ mã nào khác phụ thuộc vào việc tẩy, thì người đó có thể tạo một công cụ chọn với một bảng công văn riêng Bảng công văn toàn cầu do mô-đun quản lý có sẵn dưới dạng # Simple example presenting how persistent ID can be used to pickle # external objects by reference. import pickle import sqlite3 from collections import namedtuple # Simple class representing a record in our database. MemoRecord = namedtuple("MemoRecord", "key, task") class DBPickler(pickle.Pickler): def persistent_id(self, obj): # Instead of pickling MemoRecord as a regular class instance, we emit a # persistent ID. if isinstance(obj, MemoRecord): # Here, our persistent ID is simply a tuple, containing a tag and a # key, which refers to a specific record in the database. return ("MemoRecord", obj.key) else: # If obj does not have a persistent ID, return None. This means obj # needs to be pickled as usual. return None class DBUnpickler(pickle.Unpickler): def __init__(self, file, connection): super().__init__(file) self.connection = connection def persistent_load(self, pid): # This method is invoked whenever a persistent ID is encountered. # Here, pid is the tuple returned by DBPickler. cursor = self.connection.cursor() type_tag, key_id = pid if type_tag == "MemoRecord": # Fetch the referenced record from the database and return it. cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),)) key, task = cursor.fetchone() return MemoRecord(key, task) else: # Always raises an error if you cannot return the correct object. # Otherwise, the unpickler will think None is the object referenced # by the persistent ID. raise pickle.UnpicklingError("unsupported persistent object") def main(): import io import pprint # Initialize and populate our database. conn = sqlite3.connect(":memory:") cursor = conn.cursor() cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)") tasks = ( 'give food to fish', 'prepare group meeting', 'fight with a zebra', ) for task in tasks: cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,)) # Fetch the records to be pickled. cursor.execute("SELECT * FROM memos") memos = [MemoRecord(key, task) for key, task in cursor] # Save the records using our custom DBPickler. file = io.BytesIO() DBPickler(file).dump(memos) print("Pickled records:") pprint.pprint(memos) # Update a record, just for good measure. cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1") # Load the records from the pickle data stream. file.seek(0) memos = DBUnpickler(file, conn).load() print("Unpickled records:") pprint.pprint(memos) if __name__ == '__main__': main()10. Do đó, người ta có thể chọn sử dụng bản sao đã sửa đổi của # Simple example presenting how persistent ID can be used to pickle # external objects by reference. import pickle import sqlite3 from collections import namedtuple # Simple class representing a record in our database. MemoRecord = namedtuple("MemoRecord", "key, task") class DBPickler(pickle.Pickler): def persistent_id(self, obj): # Instead of pickling MemoRecord as a regular class instance, we emit a # persistent ID. if isinstance(obj, MemoRecord): # Here, our persistent ID is simply a tuple, containing a tag and a # key, which refers to a specific record in the database. return ("MemoRecord", obj.key) else: # If obj does not have a persistent ID, return None. This means obj # needs to be pickled as usual. return None class DBUnpickler(pickle.Unpickler): def __init__(self, file, connection): super().__init__(file) self.connection = connection def persistent_load(self, pid): # This method is invoked whenever a persistent ID is encountered. # Here, pid is the tuple returned by DBPickler. cursor = self.connection.cursor() type_tag, key_id = pid if type_tag == "MemoRecord": # Fetch the referenced record from the database and return it. cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),)) key, task = cursor.fetchone() return MemoRecord(key, task) else: # Always raises an error if you cannot return the correct object. # Otherwise, the unpickler will think None is the object referenced # by the persistent ID. raise pickle.UnpicklingError("unsupported persistent object") def main(): import io import pprint # Initialize and populate our database. conn = sqlite3.connect(":memory:") cursor = conn.cursor() cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)") tasks = ( 'give food to fish', 'prepare group meeting', 'fight with a zebra', ) for task in tasks: cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,)) # Fetch the records to be pickled. cursor.execute("SELECT * FROM memos") memos = [MemoRecord(key, task) for key, task in cursor] # Save the records using our custom DBPickler. file = io.BytesIO() DBPickler(file).dump(memos) print("Pickled records:") pprint.pprint(memos) # Update a record, just for good measure. cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1") # Load the records from the pickle data stream. file.seek(0) memos = DBUnpickler(file, conn).load() print("Unpickled records:") pprint.pprint(memos) if __name__ == '__main__': main()10 làm bảng công văn riêng Ví dụ f = io.BytesIO() p = pickle.Pickler(f) p.dispatch_table = copyreg.dispatch_table.copy() p.dispatch_table[SomeClass] = reduce_SomeClass tạo một thể hiện với một bảng công văn riêng xử lý lớp # Simple example presenting how persistent ID can be used to pickle # external objects by reference. import pickle import sqlite3 from collections import namedtuple # Simple class representing a record in our database. MemoRecord = namedtuple("MemoRecord", "key, task") class DBPickler(pickle.Pickler): def persistent_id(self, obj): # Instead of pickling MemoRecord as a regular class instance, we emit a # persistent ID. if isinstance(obj, MemoRecord): # Here, our persistent ID is simply a tuple, containing a tag and a # key, which refers to a specific record in the database. return ("MemoRecord", obj.key) else: # If obj does not have a persistent ID, return None. This means obj # needs to be pickled as usual. return None class DBUnpickler(pickle.Unpickler): def __init__(self, file, connection): super().__init__(file) self.connection = connection def persistent_load(self, pid): # This method is invoked whenever a persistent ID is encountered. # Here, pid is the tuple returned by DBPickler. cursor = self.connection.cursor() type_tag, key_id = pid if type_tag == "MemoRecord": # Fetch the referenced record from the database and return it. cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),)) key, task = cursor.fetchone() return MemoRecord(key, task) else: # Always raises an error if you cannot return the correct object. # Otherwise, the unpickler will think None is the object referenced # by the persistent ID. raise pickle.UnpicklingError("unsupported persistent object") def main(): import io import pprint # Initialize and populate our database. conn = sqlite3.connect(":memory:") cursor = conn.cursor() cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)") tasks = ( 'give food to fish', 'prepare group meeting', 'fight with a zebra', ) for task in tasks: cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,)) # Fetch the records to be pickled. cursor.execute("SELECT * FROM memos") memos = [MemoRecord(key, task) for key, task in cursor] # Save the records using our custom DBPickler. file = io.BytesIO() DBPickler(file).dump(memos) print("Pickled records:") pprint.pprint(memos) # Update a record, just for good measure. cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1") # Load the records from the pickle data stream. file.seek(0) memos = DBUnpickler(file, conn).load() print("Unpickled records:") pprint.pprint(memos) if __name__ == '__main__': main()13 một cách đặc biệt. Ngoài ra, mã class MyPickler(pickle.Pickler): dispatch_table = copyreg.dispatch_table.copy() dispatch_table[SomeClass] = reduce_SomeClass f = io.BytesIO() p = MyPickler(f) làm tương tự nhưng tất cả các phiên bản của # Simple example presenting how persistent ID can be used to pickle # external objects by reference. import pickle import sqlite3 from collections import namedtuple # Simple class representing a record in our database. MemoRecord = namedtuple("MemoRecord", "key, task") class DBPickler(pickle.Pickler): def persistent_id(self, obj): # Instead of pickling MemoRecord as a regular class instance, we emit a # persistent ID. if isinstance(obj, MemoRecord): # Here, our persistent ID is simply a tuple, containing a tag and a # key, which refers to a specific record in the database. return ("MemoRecord", obj.key) else: # If obj does not have a persistent ID, return None. This means obj # needs to be pickled as usual. return None class DBUnpickler(pickle.Unpickler): def __init__(self, file, connection): super().__init__(file) self.connection = connection def persistent_load(self, pid): # This method is invoked whenever a persistent ID is encountered. # Here, pid is the tuple returned by DBPickler. cursor = self.connection.cursor() type_tag, key_id = pid if type_tag == "MemoRecord": # Fetch the referenced record from the database and return it. cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),)) key, task = cursor.fetchone() return MemoRecord(key, task) else: # Always raises an error if you cannot return the correct object. # Otherwise, the unpickler will think None is the object referenced # by the persistent ID. raise pickle.UnpicklingError("unsupported persistent object") def main(): import io import pprint # Initialize and populate our database. conn = sqlite3.connect(":memory:") cursor = conn.cursor() cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)") tasks = ( 'give food to fish', 'prepare group meeting', 'fight with a zebra', ) for task in tasks: cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,)) # Fetch the records to be pickled. cursor.execute("SELECT * FROM memos") memos = [MemoRecord(key, task) for key, task in cursor] # Save the records using our custom DBPickler. file = io.BytesIO() DBPickler(file).dump(memos) print("Pickled records:") pprint.pprint(memos) # Update a record, just for good measure. cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1") # Load the records from the pickle data stream. file.seek(0) memos = DBUnpickler(file, conn).load() print("Unpickled records:") pprint.pprint(memos) if __name__ == '__main__': main()14 theo mặc định sẽ chia sẻ bảng công văn riêng. Mặt khác, mã copyreg.pickle(SomeClass, reduce_SomeClass) f = io.BytesIO() p = pickle.Pickler(f) sửa đổi bảng công văn chung được chia sẻ bởi tất cả người dùng của mô-đun Xử lý các đối tượng trạng tháiĐây là một ví dụ cho thấy cách sửa đổi hành vi pickling cho một lớp. Lớp # Simple example presenting how persistent ID can be used to pickle # external objects by reference. import pickle import sqlite3 from collections import namedtuple # Simple class representing a record in our database. MemoRecord = namedtuple("MemoRecord", "key, task") class DBPickler(pickle.Pickler): def persistent_id(self, obj): # Instead of pickling MemoRecord as a regular class instance, we emit a # persistent ID. if isinstance(obj, MemoRecord): # Here, our persistent ID is simply a tuple, containing a tag and a # key, which refers to a specific record in the database. return ("MemoRecord", obj.key) else: # If obj does not have a persistent ID, return None. This means obj # needs to be pickled as usual. return None class DBUnpickler(pickle.Unpickler): def __init__(self, file, connection): super().__init__(file) self.connection = connection def persistent_load(self, pid): # This method is invoked whenever a persistent ID is encountered. # Here, pid is the tuple returned by DBPickler. cursor = self.connection.cursor() type_tag, key_id = pid if type_tag == "MemoRecord": # Fetch the referenced record from the database and return it. cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),)) key, task = cursor.fetchone() return MemoRecord(key, task) else: # Always raises an error if you cannot return the correct object. # Otherwise, the unpickler will think None is the object referenced # by the persistent ID. raise pickle.UnpicklingError("unsupported persistent object") def main(): import io import pprint # Initialize and populate our database. conn = sqlite3.connect(":memory:") cursor = conn.cursor() cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)") tasks = ( 'give food to fish', 'prepare group meeting', 'fight with a zebra', ) for task in tasks: cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,)) # Fetch the records to be pickled. cursor.execute("SELECT * FROM memos") memos = [MemoRecord(key, task) for key, task in cursor] # Save the records using our custom DBPickler. file = io.BytesIO() DBPickler(file).dump(memos) print("Pickled records:") pprint.pprint(memos) # Update a record, just for good measure. cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1") # Load the records from the pickle data stream. file.seek(0) memos = DBUnpickler(file, conn).load() print("Unpickled records:") pprint.pprint(memos) if __name__ == '__main__': main()16 mở một tệp văn bản và trả về số dòng và nội dung dòng mỗi khi phương thức # Simple example presenting how persistent ID can be used to pickle # external objects by reference. import pickle import sqlite3 from collections import namedtuple # Simple class representing a record in our database. MemoRecord = namedtuple("MemoRecord", "key, task") class DBPickler(pickle.Pickler): def persistent_id(self, obj): # Instead of pickling MemoRecord as a regular class instance, we emit a # persistent ID. if isinstance(obj, MemoRecord): # Here, our persistent ID is simply a tuple, containing a tag and a # key, which refers to a specific record in the database. return ("MemoRecord", obj.key) else: # If obj does not have a persistent ID, return None. This means obj # needs to be pickled as usual. return None class DBUnpickler(pickle.Unpickler): def __init__(self, file, connection): super().__init__(file) self.connection = connection def persistent_load(self, pid): # This method is invoked whenever a persistent ID is encountered. # Here, pid is the tuple returned by DBPickler. cursor = self.connection.cursor() type_tag, key_id = pid if type_tag == "MemoRecord": # Fetch the referenced record from the database and return it. cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),)) key, task = cursor.fetchone() return MemoRecord(key, task) else: # Always raises an error if you cannot return the correct object. # Otherwise, the unpickler will think None is the object referenced # by the persistent ID. raise pickle.UnpicklingError("unsupported persistent object") def main(): import io import pprint # Initialize and populate our database. conn = sqlite3.connect(":memory:") cursor = conn.cursor() cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)") tasks = ( 'give food to fish', 'prepare group meeting', 'fight with a zebra', ) for task in tasks: cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,)) # Fetch the records to be pickled. cursor.execute("SELECT * FROM memos") memos = [MemoRecord(key, task) for key, task in cursor] # Save the records using our custom DBPickler. file = io.BytesIO() DBPickler(file).dump(memos) print("Pickled records:") pprint.pprint(memos) # Update a record, just for good measure. cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1") # Load the records from the pickle data stream. file.seek(0) memos = DBUnpickler(file, conn).load() print("Unpickled records:") pprint.pprint(memos) if __name__ == '__main__': main()17 của nó được gọi. Nếu một phiên bản # Simple example presenting how persistent ID can be used to pickle # external objects by reference. import pickle import sqlite3 from collections import namedtuple # Simple class representing a record in our database. MemoRecord = namedtuple("MemoRecord", "key, task") class DBPickler(pickle.Pickler): def persistent_id(self, obj): # Instead of pickling MemoRecord as a regular class instance, we emit a # persistent ID. if isinstance(obj, MemoRecord): # Here, our persistent ID is simply a tuple, containing a tag and a # key, which refers to a specific record in the database. return ("MemoRecord", obj.key) else: # If obj does not have a persistent ID, return None. This means obj # needs to be pickled as usual. return None class DBUnpickler(pickle.Unpickler): def __init__(self, file, connection): super().__init__(file) self.connection = connection def persistent_load(self, pid): # This method is invoked whenever a persistent ID is encountered. # Here, pid is the tuple returned by DBPickler. cursor = self.connection.cursor() type_tag, key_id = pid if type_tag == "MemoRecord": # Fetch the referenced record from the database and return it. cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),)) key, task = cursor.fetchone() return MemoRecord(key, task) else: # Always raises an error if you cannot return the correct object. # Otherwise, the unpickler will think None is the object referenced # by the persistent ID. raise pickle.UnpicklingError("unsupported persistent object") def main(): import io import pprint # Initialize and populate our database. conn = sqlite3.connect(":memory:") cursor = conn.cursor() cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)") tasks = ( 'give food to fish', 'prepare group meeting', 'fight with a zebra', ) for task in tasks: cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,)) # Fetch the records to be pickled. cursor.execute("SELECT * FROM memos") memos = [MemoRecord(key, task) for key, task in cursor] # Save the records using our custom DBPickler. file = io.BytesIO() DBPickler(file).dump(memos) print("Pickled records:") pprint.pprint(memos) # Update a record, just for good measure. cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1") # Load the records from the pickle data stream. file.seek(0) memos = DBUnpickler(file, conn).load() print("Unpickled records:") pprint.pprint(memos) if __name__ == '__main__': main()16 được chọn, tất cả các thuộc tính ngoại trừ thành viên đối tượng tệp đều được lưu. Khi phiên bản được giải nén, tệp sẽ được mở lại và quá trình đọc tiếp tục từ vị trí cuối cùng. Các phương pháp def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj32 và def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj27 được sử dụng để thực hiện hành vi này class TextReader: """Print and number lines in a text file.""" def __init__(self, filename): self.filename = filename self.file = open(filename) self.lineno = 0 def readline(self): self.lineno += 1 line = self.file.readline() if not line: return None if line.endswith('\n'): line = line[:-1] return "%i: %s" % (self.lineno, line) def __getstate__(self): # Copy the object's state from self.__dict__ which contains # all our instance attributes. Always use the dict.copy() # method to avoid modifying the original state. state = self.__dict__.copy() # Remove the unpicklable entries. del state['file'] return state def __setstate__(self, state): # Restore instance attributes (i.e., filename and lineno). self.__dict__.update(state) # Restore the previously opened file's state. To do so, we need to # reopen it and read from it until the line count is restored. file = open(self.filename) for _ in range(self.lineno): file.readline() # Finally, save the file. self.file = file Cách sử dụng mẫu có thể giống như thế này >>> reader = TextReader("hello.txt") >>> reader.readline() '1: Hello world!' >>> reader.readline() '2: I am line number two.' >>> new_reader = pickle.loads(pickle.dumps(reader)) >>> new_reader.readline() '3: Goodbye!' Giảm bớt tùy chỉnh cho các loại, chức năng và các đối tượng khácMới trong phiên bản 3. 8 Đôi khi, có thể không đủ linh hoạt. Cụ thể, chúng tôi có thể muốn tùy chỉnh việc chọn lọc dựa trên một tiêu chí khác ngoài loại của đối tượng hoặc chúng tôi có thể muốn tùy chỉnh việc chọn lọc các hàm và lớp Đối với những trường hợp đó, có thể phân lớp từ lớp và thực hiện một phương thức. Phương thức này có thể trả về một bộ rút gọn tùy ý (xem import io import pickle class MyClass: my_attribute = 1 class MyPickler(pickle.Pickler): def reducer_override(self, obj): """Custom reducer for MyClass.""" if getattr(obj, "__name__", None) == "MyClass": return type, (obj.__name__, obj.__bases__, {'my_attribute': obj.my_attribute}) else: # For any other object, fallback to usual reduction return NotImplemented f = io.BytesIO() p = MyPickler(f) p.dump(MyClass) del MyClass unpickled_class = pickle.loads(f.getvalue()) assert isinstance(unpickled_class, type) assert unpickled_class.__name__ == "MyClass" assert unpickled_class.my_attribute == 15). Ngoài ra, nó có thể trả lại class ZeroCopyByteArray(bytearray): def __reduce_ex__(self, protocol): if protocol >= 5: return type(self)._reconstruct, (PickleBuffer(self),), None else: # PickleBuffer is forbidden with pickle protocols <= 4. return type(self)._reconstruct, (bytearray(self),) @classmethod def _reconstruct(cls, obj): with memoryview(obj) as m: # Get a handle over the original buffer object obj = m.obj if type(obj) is cls: # Original buffer object is a ZeroCopyByteArray, return it # as-is. return obj else: return cls(obj)4 để dự phòng cho hành vi truyền thống Nếu cả và được xác định, thì phương thức sẽ được ưu tiên Ghi chú Vì lý do hiệu suất, có thể không được gọi cho các đối tượng sau. import io import pickle class MyClass: my_attribute = 1 class MyPickler(pickle.Pickler): def reducer_override(self, obj): """Custom reducer for MyClass.""" if getattr(obj, "__name__", None) == "MyClass": return type, (obj.__name__, obj.__bases__, {'my_attribute': obj.my_attribute}) else: # For any other object, fallback to usual reduction return NotImplemented f = io.BytesIO() p = MyPickler(f) p.dump(MyClass) del MyClass unpickled_class = pickle.loads(f.getvalue()) assert isinstance(unpickled_class, type) assert unpickled_class.__name__ == "MyClass" assert unpickled_class.my_attribute == 10, def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj23, def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj24 và các trường hợp chính xác của , , , , , , , và Đây là một ví dụ đơn giản nơi chúng tôi cho phép tẩy và xây dựng lại một lớp nhất định ________số 8_______ Bộ đệm ngoài băng tầnMới trong phiên bản 3. 8 Trong một số ngữ cảnh, mô-đun được sử dụng để truyền một lượng lớn dữ liệu. Do đó, điều quan trọng là phải giảm thiểu số lượng bản sao bộ nhớ, để duy trì hiệu suất và mức tiêu thụ tài nguyên. Tuy nhiên, hoạt động bình thường của mô-đun, khi nó chuyển đổi cấu trúc giống như đồ thị của các đối tượng thành một luồng byte tuần tự, về bản chất liên quan đến việc sao chép dữ liệu đến và từ luồng dưa chua Hạn chế này có thể được loại bỏ nếu cả nhà cung cấp (việc triển khai các loại đối tượng được truyền) và người tiêu dùng (việc triển khai hệ thống truyền thông) đều hỗ trợ các phương tiện truyền ngoài băng được cung cấp bởi giao thức pickle 5 trở lên API nhà cung cấpCác đối tượng dữ liệu lớn được chọn phải triển khai phương thức def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj98 dành riêng cho giao thức 5 trở lên, phương thức này trả về một thể hiện (thay vì e. g. một đối tượng) cho bất kỳ dữ liệu lớn nào Một đối tượng báo hiệu rằng bộ đệm bên dưới đủ điều kiện để truyền dữ liệu ngoài băng tần. Những đối tượng đó vẫn tương thích với việc sử dụng bình thường của mô-đun. Tuy nhiên, người tiêu dùng cũng có thể chọn tham gia để cho biết rằng họ sẽ tự xử lý các bộ đệm đó API người tiêu dùngMột hệ thống truyền thông có thể cho phép xử lý tùy chỉnh các đối tượng được tạo khi sắp xếp theo thứ tự một biểu đồ đối tượng Ở bên gửi, nó cần chuyển một đối số buffer_callback tới (hoặc tới hàm or), đối số này sẽ được gọi với mỗi đối số được tạo trong khi chọn biểu đồ đối tượng. Bộ đệm được tích lũy bởi buffer_callback sẽ không thấy dữ liệu của chúng được sao chép vào luồng dưa chua, chỉ một điểm đánh dấu rẻ tiền sẽ được chèn vào Ở phía nhận, nó cần truyền một đối số bộ đệm tới (hoặc tới hàm or), đây là một lần lặp của các bộ đệm đã được chuyển tới buffer_callback. Iterable đó sẽ tạo ra các bộ đệm theo cùng thứ tự khi chúng được chuyển đến buffer_callback. Những bộ đệm đó sẽ cung cấp dữ liệu mà các nhà tái cấu trúc của các đối tượng mong đợi mà quá trình tẩy đã tạo ra các đối tượng ban đầu Giữa bên gửi và bên nhận, hệ thống liên lạc được tự do triển khai cơ chế truyền của riêng mình đối với bộ đệm ngoài băng tần. Khả năng tối ưu hóa bao gồm việc sử dụng bộ nhớ dùng chung hoặc nén phụ thuộc vào kiểu dữ liệu Ví dụĐây là một ví dụ tầm thường trong đó chúng tôi triển khai một lớp con có thể tham gia vào quá trình chọn bộ đệm ngoài dải class ZeroCopyByteArray(bytearray): def __reduce_ex__(self, protocol): if protocol >= 5: return type(self)._reconstruct, (PickleBuffer(self),), None else: # PickleBuffer is forbidden with pickle protocols <= 4. return type(self)._reconstruct, (bytearray(self),) @classmethod def _reconstruct(cls, obj): with memoryview(obj) as m: # Get a handle over the original buffer object obj = m.obj if type(obj) is cls: # Original buffer object is a ZeroCopyByteArray, return it # as-is. return obj else: return cls(obj) Trình tái cấu trúc (phương thức lớp # Simple example presenting how persistent ID can be used to pickle # external objects by reference. import pickle import sqlite3 from collections import namedtuple # Simple class representing a record in our database. MemoRecord = namedtuple("MemoRecord", "key, task") class DBPickler(pickle.Pickler): def persistent_id(self, obj): # Instead of pickling MemoRecord as a regular class instance, we emit a # persistent ID. if isinstance(obj, MemoRecord): # Here, our persistent ID is simply a tuple, containing a tag and a # key, which refers to a specific record in the database. return ("MemoRecord", obj.key) else: # If obj does not have a persistent ID, return None. This means obj # needs to be pickled as usual. return None class DBUnpickler(pickle.Unpickler): def __init__(self, file, connection): super().__init__(file) self.connection = connection def persistent_load(self, pid): # This method is invoked whenever a persistent ID is encountered. # Here, pid is the tuple returned by DBPickler. cursor = self.connection.cursor() type_tag, key_id = pid if type_tag == "MemoRecord": # Fetch the referenced record from the database and return it. cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),)) key, task = cursor.fetchone() return MemoRecord(key, task) else: # Always raises an error if you cannot return the correct object. # Otherwise, the unpickler will think None is the object referenced # by the persistent ID. raise pickle.UnpicklingError("unsupported persistent object") def main(): import io import pprint # Initialize and populate our database. conn = sqlite3.connect(":memory:") cursor = conn.cursor() cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)") tasks = ( 'give food to fish', 'prepare group meeting', 'fight with a zebra', ) for task in tasks: cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,)) # Fetch the records to be pickled. cursor.execute("SELECT * FROM memos") memos = [MemoRecord(key, task) for key, task in cursor] # Save the records using our custom DBPickler. file = io.BytesIO() DBPickler(file).dump(memos) print("Pickled records:") pprint.pprint(memos) # Update a record, just for good measure. cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1") # Load the records from the pickle data stream. file.seek(0) memos = DBUnpickler(file, conn).load() print("Unpickled records:") pprint.pprint(memos) if __name__ == '__main__': main()60) trả về đối tượng cung cấp của bộ đệm nếu nó có đúng loại. Đây là một cách dễ dàng để mô phỏng hành vi không sao chép trên mẫu đồ chơi này Về phía người tiêu dùng, chúng tôi có thể chọn các đối tượng đó theo cách thông thường, khi không được đánh dấu sẽ cung cấp cho chúng tôi một bản sao của đối tượng ban đầu def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj0 Nhưng nếu chúng tôi chuyển một buffer_callback và sau đó trả lại bộ đệm tích lũy khi hủy xác thực, chúng tôi có thể lấy lại đối tượng ban đầu def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj1 Ví dụ này bị giới hạn bởi thực tế là phân bổ bộ nhớ của chính nó. bạn không thể tạo một thể hiện được hỗ trợ bởi bộ nhớ của đối tượng khác. Tuy nhiên, các kiểu dữ liệu của bên thứ ba chẳng hạn như mảng NumPy không có giới hạn này và cho phép sử dụng tính năng chọn lọc không sao chép (hoặc tạo càng ít bản sao càng tốt) khi chuyển giữa các quy trình hoặc hệ thống riêng biệt Xem thêm PEP 574 – Pickle giao thức 5 với dữ liệu ngoài băng tần Hạn chế toàn cầuTheo mặc định, unpickling sẽ nhập bất kỳ lớp hoặc chức năng nào mà nó tìm thấy trong dữ liệu pickle. Đối với nhiều ứng dụng, hành vi này là không thể chấp nhận được vì nó cho phép trình giải nén nhập và gọi mã tùy ý. Chỉ cần xem luồng dữ liệu dưa chua thủ công này sẽ làm gì khi được tải def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj2 Trong ví dụ này, trình giải mã nhập hàm và sau đó áp dụng đối số chuỗi “echo hello world”. Mặc dù ví dụ này không gây khó chịu, nhưng không khó để tưởng tượng một ví dụ có thể làm hỏng hệ thống của bạn Vì lý do này, bạn có thể muốn kiểm soát những gì được bỏ chọn bằng cách tùy chỉnh. Không giống như tên gọi của nó, được gọi bất cứ khi nào một toàn cục (i. e. , một lớp hoặc một chức năng) được yêu cầu. Do đó, có thể cấm hoàn toàn toàn cầu hoặc hạn chế chúng trong một tập hợp con an toàn Dưới đây là một ví dụ về trình giải nén chỉ cho phép tải một số lớp an toàn từ mô-đun def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj3 Cách sử dụng mẫu của trình gỡ chọn của chúng tôi hoạt động như dự kiến def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj4 Như các ví dụ của chúng tôi cho thấy, bạn phải cẩn thận với những gì bạn cho phép bỏ chọn. Do đó, nếu vấn đề bảo mật là vấn đề đáng lo ngại, bạn có thể muốn xem xét các giải pháp thay thế như API sắp xếp thứ tự trong hoặc các giải pháp của bên thứ ba Hiệu suấtCác phiên bản gần đây của giao thức pickle (từ giao thức 2 trở lên) có tính năng mã hóa nhị phân hiệu quả cho một số tính năng phổ biến và các loại tích hợp. Ngoài ra, mô-đun có trình tối ưu hóa trong suốt được viết bằng C ví dụĐối với mã đơn giản nhất, hãy sử dụng hàm và def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj5 Ví dụ sau đọc dữ liệu được chọn kết quả def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj6 Xem thêm mô-đunĐăng ký trình tạo giao diện Pickle cho các loại tiện ích mở rộng mô-đunCác công cụ để làm việc và phân tích dữ liệu được chọn lọc mô-đunCơ sở dữ liệu được lập chỉ mục của các đối tượng; mô-đunSao chép đối tượng nông và sâu mô-đunSê-ri hóa hiệu suất cao của các loại tích hợp chú thích Đừng nhầm lẫn điều này với mô-đun Đây là lý do tại sao các chức năng không thể được chọn. tất cả các hàm def save(obj): return (obj.__class__, obj.__dict__) def restore(cls, attributes): obj = cls.__new__(cls) obj.__dict__.update(attributes) return obj26 có cùng tên. # Simple example presenting how persistent ID can be used to pickle # external objects by reference. import pickle import sqlite3 from collections import namedtuple # Simple class representing a record in our database. MemoRecord = namedtuple("MemoRecord", "key, task") class DBPickler(pickle.Pickler): def persistent_id(self, obj): # Instead of pickling MemoRecord as a regular class instance, we emit a # persistent ID. if isinstance(obj, MemoRecord): # Here, our persistent ID is simply a tuple, containing a tag and a # key, which refers to a specific record in the database. return ("MemoRecord", obj.key) else: # If obj does not have a persistent ID, return None. This means obj # needs to be pickled as usual. return None class DBUnpickler(pickle.Unpickler): def __init__(self, file, connection): super().__init__(file) self.connection = connection def persistent_load(self, pid): # This method is invoked whenever a persistent ID is encountered. # Here, pid is the tuple returned by DBPickler. cursor = self.connection.cursor() type_tag, key_id = pid if type_tag == "MemoRecord": # Fetch the referenced record from the database and return it. cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),)) key, task = cursor.fetchone() return MemoRecord(key, task) else: # Always raises an error if you cannot return the correct object. # Otherwise, the unpickler will think None is the object referenced # by the persistent ID. raise pickle.UnpicklingError("unsupported persistent object") def main(): import io import pprint # Initialize and populate our database. conn = sqlite3.connect(":memory:") cursor = conn.cursor() cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)") tasks = ( 'give food to fish', 'prepare group meeting', 'fight with a zebra', ) for task in tasks: cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,)) # Fetch the records to be pickled. cursor.execute("SELECT * FROM memos") memos = [MemoRecord(key, task) for key, task in cursor] # Save the records using our custom DBPickler. file = io.BytesIO() DBPickler(file).dump(memos) print("Pickled records:") pprint.pprint(memos) # Update a record, just for good measure. cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1") # Load the records from the pickle data stream. file.seek(0) memos = DBUnpickler(file, conn).load() print("Unpickled records:") pprint.pprint(memos) if __name__ == '__main__': main()80 Ngoại lệ được đưa ra có thể sẽ là một hoặc một nhưng nó có thể là một thứ khác Mô-đun sử dụng giao thức này cho các hoạt động sao chép nông và sâu Hạn chế về ký tự chữ và số là do các ID liên tục trong giao thức 0 được phân định bằng ký tự xuống dòng. Do đó, nếu bất kỳ loại ký tự dòng mới nào xuất hiện trong ID liên tục, dữ liệu được chọn sẽ không thể đọc được Làm cách nào để chuyển đổi tệp thành nhị phân trong Python?Hàm open() mở tệp ở định dạng văn bản theo mặc định. Để mở tệp ở định dạng nhị phân, hãy thêm 'b' vào tham số chế độ . Do đó, chế độ "rb" mở tệp ở định dạng nhị phân để đọc, trong khi chế độ "wb" mở tệp ở định dạng nhị phân để ghi.
Phương pháp nào được sử dụng để chuyển đổi các đối tượng Python để ghi dữ liệu ở dạng nhị phân?“ Pickling ” là quá trình theo đó hệ thống phân cấp đối tượng Python được chuyển đổi thành luồng byte và “unpickling” là thao tác ngược lại, .
Đơn vị bộ nhớ nào được sử dụng để lưu tệp nhị phân trong Python?Tệp nhị phân cũng được lưu trữ dưới dạng byte (0 và 1) , nhưng không giống như tệp văn bản, những byte này không đại diện cho ASCII .
Làm cách nào để tạo tệp nhị phân?Cách tạo tệp nhị phân . Thêm không gian tên vào trang mã của dự án của bạn. Viết và đọc tệp yêu cầu không gian tên "IO". . Tạo biến dòng tệp và gán nó cho luồng nhị phân. . Ghi vào tệp nhị phân bằng chức năng "Ghi". . Đóng tệp sau khi tất cả thông tin đã được lưu vào tệp |