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
Lập trình viên tên Tim

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 obj
7 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ác

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() 2

Python 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

  • Mô-đun theo dõi các đối tượng mà nó đã đánh số thứ tự, để sau này các tham chiếu đến cùng một đối tượng sẽ không được đánh số thứ tự nữa. không làm điều này

    Điều này có ý nghĩa đối với cả đối tượng đệ quy và chia sẻ đối tượng. Các đối tượng đệ quy là các đối tượng chứa các tham chiếu đến chính chúng. Những thứ này không được xử lý bởi nguyên soái và trên thực tế, việc cố gắng sắp xếp theo thứ tự các đối tượng đệ quy sẽ làm hỏng trình thông dịch Python của bạn. Chia sẻ đối tượng xảy ra khi có nhiều tham chiếu đến cùng một đối tượng ở các vị trí khác nhau trong hệ thống phân cấp đối tượng được tuần tự hóa. lưu trữ các đối tượng như vậy chỉ một lần và đảm bảo rằng tất cả các tham chiếu khác trỏ đến bản sao chính. Các đối tượng được chia sẻ vẫn được chia sẻ, điều này có thể rất quan trọng đối với các đối tượng có thể thay đổi

  • không thể được sử dụng để tuần tự hóa các lớp do người dùng định nghĩa và các thể hiện của chúng. có thể lưu và khôi phục các thể hiện của lớp một cách minh bạch, tuy nhiên, định nghĩa lớp phải có thể nhập được và nằm trong cùng một mô-đun như khi đối tượng được lưu trữ

  • Định dạng tuần tự hóa không được đảm bảo để có thể di chuyển trên các phiên bản Python. Bởi vì công việc chính của nó trong cuộc sống là 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, nên những người triển khai Python có quyền thay đổi định dạng tuần tự hóa theo những cách không tương thích ngược nếu có nhu cầu. Định dạng tuần tự hóa được đảm bảo tương thích ngược trên các bản phát hành Python miễn là một giao thức pickle tương thích được chọn và mã pickling và unpickling xử lý các khác biệt về loại Python 2 đến Python 3 nếu dữ liệu của bạn vượt qua ranh giới ngôn ngữ thay đổi phá vỡ duy nhất đó

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() 1

Có 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)

  • JSON là định dạng tuần tự hóa văn bản (nó xuất ra văn bản unicode, mặc dù sau đó hầu hết thời gian nó được mã hóa thành

    f = io.BytesIO()
    p = pickle.Pickler(f)
    p.dispatch_table = copyreg.dispatch_table.copy()
    p.dispatch_table[SomeClass] = reduce_SomeClass
    
    8), trong khi pickle là định dạng tuần tự hóa nhị phân;

  • JSON có thể đọc được bằng con người, trong khi dưa chua thì không;

  • JSON có thể tương tác và được sử dụng rộng rãi bên ngoài hệ sinh thái Python, trong khi dưa chua là dành riêng cho Python;

  • Theo mặc định, JSON chỉ có thể đại diện cho một tập hợp con của các loại tích hợp Python và không có lớp tùy chỉnh nào;

  • Không giống như dưa chua, bản thân việc giải tuần tự hóa JSON không đáng tin cậy không tạo ra lỗ hổng thực thi mã tùy ý

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

  • Giao thức phiên bản 0 là giao thức gốc “con người có thể đọc được” và tương thích ngược với các phiên bản Python cũ hơn

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

  • Giao thức phiên bản 2 đã được giới thiệu trong Python 2. 3. Nó cung cấp hiệu quả hơn nhiều ngâm của. Tham khảo PEP 307 để biết thông tin về các cải tiến do giao thức 2 mang lại

  • Giao thức phiên bản 3 đã được thêm vào Python 3. 0. Nó có hỗ trợ rõ ràng cho các đối tượng và Python 2 không thể giải nén. x. Đây là giao thức mặc định trong Python 3. 0–3. 7

  • Giao thức phiên bản 4 đã được thêm vào Python 3. 4. Nó thêm hỗ trợ cho các đối tượng rất lớn, chọn nhiều loại đối tượng hơn và một số tối ưu hóa định dạng dữ liệu. Nó là giao thức mặc định bắt đầu với Python 3. 8. Tham khảo PEP 3154 để biết thông tin về các cải tiến do giao thức 4 mang lại

  • Giao thức phiên bản 5 đã được thêm vào Python 3. 8. Nó bổ sung hỗ trợ cho dữ liệu ngoài băng tần và tăng tốc cho dữ liệu trong băng tần. Tham khảo PEP 574 để biết thông tin về các cải tiến do giao thức 5 mang lạ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_PROTOCOL

Mộ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_PROTOCOL

Mộ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 = file
3

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 chua

Lớ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ẩy

Lỗ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ọn

Lỗ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 == 1
0, 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_table

Bả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 == 1
5

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 == 1
5 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

nhanh

khô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 obj
01 để 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 obj
13 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 obj
14,
def save(obj):
    return (obj.__class__, obj.__dict__)

def restore(cls, attributes):
    obj = cls.__new__(cls)
    obj.__dict__.update(attributes)
    return obj
15

lớ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 obj
20 (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áp

phá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

  • 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 == 1
    
    0,
    def save(obj):
        return (obj.__class__, obj.__dict__)
    
    def restore(cls, attributes):
        obj = cls.__new__(cls)
        obj.__dict__.update(attributes)
        return obj
    
    23 và
    def save(obj):
        return (obj.__class__, obj.__dict__)
    
    def restore(cls, attributes):
        obj = cls.__new__(cls)
        obj.__dict__.update(attributes)
        return obj
    
    24;

  • số nguyên, số dấu phảy động, số phức;

  • chuỗi, byte, mảng phụ;

  • bộ dữ liệu, danh sách, bộ và từ điển chỉ chứa các đối tượng có thể chọn được;

  • các chức năng (tích hợp sẵn và do người dùng xác định) có thể truy cập từ cấp cao nhất của mô-đun (sử dụng , không phải );

  • các lớp có thể truy cập từ cấp cao nhất của mô-đun;

  • thể hiện của các lớp như vậy mà kết quả của việc gọi

    def save(obj):
        return (obj.__class__, obj.__dict__)
    
    def restore(cls, attributes):
        obj = cls.__new__(cls)
        obj.__dict__.update(attributes)
        return obj
    
    27 là có thể chọn được (xem phần để biết chi tiết)

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 obj
31 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 obj
32 của lớp

Phiên bản lớp Pickling

Trong 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 obj
33 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 obj
36 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 obj
42 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

  • Đối với một lớp không có thể hiện và không, trạng thái mặc định là

    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 == 1
    
    0

  • Đối với một lớp có thể hiện và không có, trạng thái mặc định là

    def save(obj):
        return (obj.__class__, obj.__dict__)
    
    def restore(cls, attributes):
        obj = cls.__new__(cls)
        obj.__dict__.update(attributes)
        return obj
    
    54

  • Đối với một lớp có một thể hiện và , trạng thái mặc định là một bộ bao gồm hai từ điển.

    def save(obj):
        return (obj.__class__, obj.__dict__)
    
    def restore(cls, attributes):
        obj = cls.__new__(cls)
        obj.__dict__.update(attributes)
        return obj
    
    54 và từ điển ánh xạ tên vị trí tới giá trị vị trí. Chỉ các vị trí có giá trị mới được bao gồm trong phần sau

  • Đối với một lớp có và không có thể hiện , trạng thái mặc định là một bộ có mục đầu tiên là

    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 == 1
    
    0 và mục thứ hai của nó là từ điển ánh xạ tên vị trí tới giá trị vị trí được mô tả trong dấu đầu dòng trước đó

Đã 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 obj
27 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 obj
27 và
def save(obj):
    return (obj.__class__, obj.__dict__)

def restore(cls, attributes):
    obj = cls.__new__(cls)
    obj.__dict__.update(attributes)
    return obj
32

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 obj
68,
def save(obj):
    return (obj.__class__, obj.__dict__)

def restore(cls, attributes):
    obj = cls.__new__(cls)
    obj.__dict__.update(attributes)
    return obj
69 hoặc
def save(obj):
    return (obj.__class__, obj.__dict__)

def restore(cls, attributes):
    obj = cls.__new__(cls)
    obj.__dict__.update(attributes)
    return obj
70 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 obj
35 để 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 obj
33 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 == 1
5. 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 == 1
5 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 obj
34,
def save(obj):
    return (obj.__class__, obj.__dict__)

def restore(cls, attributes):
    obj = cls.__new__(cls)
    obj.__dict__.update(attributes)
    return obj
27 và
def save(obj):
    return (obj.__class__, obj.__dict__)

def restore(cls, attributes):
    obj = cls.__new__(cls)
    obj.__dict__.update(attributes)
    return obj
32) 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 == 1
5 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 == 1
0 làm giá trị của chúng. Ngữ nghĩa của từng mục theo thứ tự

  • Một đối tượng có thể gọi được sẽ được gọi để tạo phiên bản ban đầu của đối tượng

  • Một bộ đối số cho đối tượng có thể gọi được. Một bộ dữ liệu trống phải được cung cấp nếu khả năng gọi được không chấp nhận bất kỳ đối số nào

  • Tùy chọn, trạng thái của đối tượng, sẽ được chuyển đến phương thức của đối tượng như đã mô tả trước đây. Nếu đối tượng không có phương thức như vậy thì giá trị phải là một từ điển và nó sẽ được thêm vào thuộc tính của đối tượng

  • Tùy chọn, một trình vòng lặp (chứ không phải một chuỗi) mang lại các mục liên tiếp. Các mục này sẽ được thêm vào đối tượng bằng cách sử dụng

    def save(obj):
        return (obj.__class__, obj.__dict__)
    
    def restore(cls, attributes):
        obj = cls.__new__(cls)
        obj.__dict__.update(attributes)
        return obj
    
    83 hoặc theo lô bằng cách sử dụng
    def save(obj):
        return (obj.__class__, obj.__dict__)
    
    def restore(cls, attributes):
        obj = cls.__new__(cls)
        obj.__dict__.update(attributes)
        return obj
    
    84. Điều này chủ yếu được sử dụng cho các lớp con danh sách, nhưng có thể được sử dụng bởi các lớp khác miễn là chúng có các 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 obj
    
    85 và
    def save(obj):
        return (obj.__class__, obj.__dict__)
    
    def restore(cls, attributes):
        obj = cls.__new__(cls)
        obj.__dict__.update(attributes)
        return obj
    
    86 với chữ ký thích hợp. (Việc sử dụng
    def save(obj):
        return (obj.__class__, obj.__dict__)
    
    def restore(cls, attributes):
        obj = cls.__new__(cls)
        obj.__dict__.update(attributes)
        return obj
    
    85 hoặc
    def save(obj):
        return (obj.__class__, obj.__dict__)
    
    def restore(cls, attributes):
        obj = cls.__new__(cls)
        obj.__dict__.update(attributes)
        return obj
    
    86 tùy thuộc vào phiên bản giao thức dưa muối được sử dụng cũng như số lượng mục cần thêm vào, vì vậy cả hai đều phải được hỗ trợ. )

  • Theo tùy chọn, một trình lặp (không phải trình tự) mang lại các cặp khóa-giá trị liên tiếp. Các mục này sẽ được lưu trữ vào đối tượng bằng cách sử dụng

    def save(obj):
        return (obj.__class__, obj.__dict__)
    
    def restore(cls, attributes):
        obj = cls.__new__(cls)
        obj.__dict__.update(attributes)
        return obj
    
    89. Điều này chủ yếu được sử dụng cho các lớp con từ điển, nhưng có thể được sử dụng bởi các lớp khác miễn là chúng thực hiện

  • Tùy chọn, có thể gọi được với chữ ký

    def save(obj):
        return (obj.__class__, obj.__dict__)
    
    def restore(cls, attributes):
        obj = cls.__new__(cls)
        obj.__dict__.update(attributes)
        return obj
    
    91. Khả năng gọi này cho phép người dùng kiểm soát theo chương trình hành vi cập nhật trạng thái của một đối tượng cụ thể, thay vì sử dụng phương thức tĩnh của
    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. Nếu không phải là
    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 == 1
    
    0, cái có thể gọi này sẽ được ưu tiên hơn cái của
    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

    Mới trong phiên bản 3. 8. Mục bộ thứ sáu tùy chọn,

    def save(obj):
        return (obj.__class__, obj.__dict__)
    
    def restore(cls, attributes):
        obj = cls.__new__(cls)
        obj.__dict__.update(attributes)
        return obj
    
    91, đã được thêm vào.

đối tượng. __reduce_ex__(giao thức)

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ài

Vì 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 == 1
0 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 == 1
0 đượ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ăn

Nế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 obj
32 và
def save(obj):
    return (obj.__class__, obj.__dict__)

def restore(cls, attributes):
    obj = cls.__new__(cls)
    obj.__dict__.update(attributes)
    return obj
27 đượ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ác

Mớ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 == 1
5). 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 == 1
0,
def save(obj):
    return (obj.__class__, obj.__dict__)

def restore(cls, attributes):
    obj = cls.__new__(cls)
    obj.__dict__.update(attributes)
    return obj
23,
def save(obj):
    return (obj.__class__, obj.__dict__)

def restore(cls, attributes):
    obj = cls.__new__(cls)
    obj.__dict__.update(attributes)
    return obj
24 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ần

Mớ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ấp

Cá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 obj
98 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ùng

Mộ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 obj
0

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 obj
1

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ầu

Theo 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 obj
2

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 obj
3

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 obj
4

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ất

Cá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 obj
5

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 obj
6

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ô-đun

Các công cụ để làm việc và phân tích dữ liệu được chọn lọc

mô-đun

Cơ sở dữ liệu được lập chỉ mục của các đối tượng;

mô-đun

Sao chép đối tượng nông và sâu

mô-đun

Sê-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 obj
26 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