pickle.md
1> **Источник:** https://python-all.ru/3.6/library/pickle.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 12.1. [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle) – сериализация объектов Python89**Исходный код:** [Lib/pickle.py](https://python-all.ru/src/3.6/Lib/pickle.py)1011---1213Модуль [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle) реализует двоичные протоколы для сериализации и de-сериализации структуры объектов Python. *«Упаковка»* – это процесс преобразования иерархии объектов Python в поток байтов, а *«распаковка»* – обратная операция, при которой поток байтов (из [двоичного файла](https://python-all.ru/3.6/glossary.html#term-binary-file) или [байтоподобного объекта](https://python-all.ru/3.6/glossary.html#term-bytes-like-object)) преобразуется обратно в иерархию объектов. Упаковка (и распаковка) также известна как «сериализация», «маршалинг», [1](https://python-all.ru/3.6/library/pickle.html#id6) или «уплощение»; однако, чтобы избежать путаницы, здесь используются термины «упаковка» и «распаковка».1415> **Предупреждение**16>17> Модуль [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle) не защищён от ошибочных или вредоносных данных. Никогда не десериализуйте данные, полученные из ненадёжного или непроверенного источника.1819## 12.1.1. Взаимосвязь с другими модулями Python2021### 12.1.1.1. Сравнение с `marshal`2223В Python есть более примитивный модуль сериализации [`marshal`](https://python-all.ru/3.6/library/marshal.html#module-marshal), но в целом [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle) всегда должен быть предпочтительным способом сериализации объектов Python. [`marshal`](https://python-all.ru/3.6/library/marshal.html#module-marshal) существует в первую очередь для поддержки файлов `.pyc` в Python.2425Модуль [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle) отличается от [`marshal`](https://python-all.ru/3.6/library/marshal.html#module-marshal) несколькими важными особенностями:2627- Модуль [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle) отслеживает уже сериализованные объекты, чтобы последующие ссылки на тот же объект не сериализовались повторно. [`marshal`](https://python-all.ru/3.6/library/marshal.html#module-marshal) этого не делает.2829 This has implications both for recursive objects and object sharing. Recursive objects are objects that contain references to themselves. These are not handled by marshal, and in fact, attempting to marshal recursive objects will crash your Python interpreter. Object sharing happens when there are multiple references to the same object in different places in the object hierarchy being serialized. [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle) stores such objects only once, and ensures that all other references point to the master copy. Shared objects remain shared, which can be very important for mutable objects.30- [`marshal`](https://python-all.ru/3.6/library/marshal.html#module-marshal) нельзя использовать для сериализации пользовательских классов и их экземпляров. [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle) может прозрачно сохранять и восстанавливать экземпляры классов, однако определение класса должно быть импортируемо и находиться в том же модуле, что и при сохранении объекта.31- Формат сериализации [`marshal`](https://python-all.ru/3.6/library/marshal.html#module-marshal) не гарантирует переносимости между версиями Python. Поскольку его основная задача – поддержка файлов `.pyc`, разработчики Python оставляют за собой право изменять формат сериализации несовместимым с предыдущими версиями образом, если возникнет необходимость. Формат сериализации [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle) гарантирует обратную совместимость между выпусками Python.3233### 12.1.1.2. Сравнение с `json`3435Существуют принципиальные различия между протоколами pickle и [JSON (JavaScript Object Notation)](https://python-all.ru/3.6/library/pickle.html):3637- JSON – это текстовый формат сериализации (он выводит текст в юникоде, хотя чаще всего затем кодируется в `utf-8`), тогда как pickle – двоичный формат сериализации;38- JSON удобочитаем, а pickle – нет;39- JSON интероперабелен и широко используется за пределами экосистемы Python, тогда как pickle является специфичным для Python;40- JSON по умолчанию может представлять лишь подмножество встроенных типов Python и не поддерживает пользовательские классы; pickle же может представлять огромное количество типов Python (многие из них автоматически, благодаря умелому использованию средств интроспекции Python; сложные случаи можно решить, реализовав [специальные объектные API](https://python-all.ru/3.6/library/pickle.html#pickle-inst)).4142> **См. также**43>44> Модуль [`json`](https://python-all.ru/3.6/library/json.html#module-json): модуль стандартной библиотеки, обеспечивающий сериализацию и десериализацию JSON.4546## 12.1.2. Формат потока данных4748Формат данных, используемый [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle), является специфичным для Python. Это даёт преимущество – нет ограничений, накладываемых внешними стандартами вроде JSON или XDR (которые не могут представлять разделяемые указатели); однако это означает, что программы на других языках могут не суметь восстановить объекты Python, сериализованные с помощью pickle.4950По умолчанию формат данных [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle) использует относительно компактное двоичное представление. Если вам нужны оптимальные характеристики размера, вы можете эффективно [сжимать](https://python-all.ru/3.6/library/archiving.html) упакованные данные.5152Модуль [`pickletools`](https://python-all.ru/3.6/library/pickletools.html#module-pickletools) содержит инструменты для анализа потоков данных, созданных [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle). Исходный код [`pickletools`](https://python-all.ru/3.6/library/pickletools.html#module-pickletools) содержит обширные комментарии об опкодах, используемых протоколами pickle.5354В настоящее время существует 5 различных протоколов, которые можно использовать для сериализации. Чем выше используемый протокол, тем более новая версия Python требуется для чтения созданного pickle.5556- Протокол версии 0 – это исходный «человекочитаемый» протокол, обратно совместимый с более ранними версиями Python.57- Протокол версии 1 – это старый двоичный формат, также совместимый с более ранними версиями Python.58- Протокол версии 2 был представлен в Python 2.3. Он обеспечивает гораздо более эффективную сериализацию [классов нового стиля](https://python-all.ru/3.6/glossary.html#term-new-style-class). Дополнительную информацию об улучшениях, внесённых протоколом 2, см. в [**PEP 307**](https://python-all.ru/3.6/library/pickle.html).59- Протокол версии 3 был добавлен в Python 3.0. Он имеет явную поддержку объектов [`bytes`](https://python-all.ru/3.6/library/stdtypes.html#bytes) и не может быть десериализован Python 2.x. Это протокол по умолчанию и рекомендуемый протокол, когда требуется совместимость с другими версиями Python 3.60- Протокол версии 4 был добавлен в Python 3.4. Он добавляет поддержку очень больших объектов, сериализацию большего числа типов объектов и некоторые оптимизации формата данных. Обратитесь к [**PEP 3154**](https://python-all.ru/3.6/library/pickle.html) для получения информации об улучшениях, внесённых протоколом 4.6162> **Примечание**63>64> Сериализация – это более примитивное понятие, чем сохранение (persistence); хотя [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle) читает и записывает файловые объекты, он не решает ни проблему именования сохраняемых объектов, ни (ещё более сложную) проблему параллельного доступа к сохраняемым объектам. Модуль [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle) может преобразовать сложный объект в поток байтов и обратно – в объект с той же внутренней структурой. Возможно, самое очевидное применение этих потоков байтов – запись в файл, но также можно передавать их по сети или хранить в базе данных. Модуль [`shelve`](https://python-all.ru/3.6/library/shelve.html#module-shelve) предоставляет простой интерфейс для упаковки (pickle) и распаковки (unpickle) объектов в файлах баз данных в стиле DBM.6566## 12.1.3. Интерфейс модуля6768Чтобы сериализовать иерархию объектов, достаточно вызвать функцию [`dumps()`](https://python-all.ru/3.6/library/pickle.html#pickle.dumps). Аналогично, для десериализации потока данных вызывается функция [`loads()`](https://python-all.ru/3.6/library/pickle.html#pickle.loads). Однако если требуется более тонкий контроль над сериализацией и десериализацией, можно создать объект [`Pickler`](https://python-all.ru/3.6/library/pickle.html#pickle.Pickler) или [`Unpickler`](https://python-all.ru/3.6/library/pickle.html#pickle.Unpickler) соответственно.6970Модуль [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle) предоставляет следующие константы:7172#### `pickle.HIGHEST_PROTOCOL`7374Целое число – наивысшая доступная [версия протокола](https://python-all.ru/3.6/library/pickle.html#pickle-protocols). Это значение можно передавать в качестве аргумента *протокола* функциям [`dump()`](https://python-all.ru/3.6/library/pickle.html#pickle.dump) и [`dumps()`](https://python-all.ru/3.6/library/pickle.html#pickle.dumps), а также конструктору [`Pickler`](https://python-all.ru/3.6/library/pickle.html#pickle.Pickler).7576#### `pickle.DEFAULT_PROTOCOL`7778Целое число – версия [протокола по умолчанию](https://python-all.ru/3.6/library/pickle.html#pickle-protocols), используемая для сериализации. Может быть меньше [`HIGHEST_PROTOCOL`](https://python-all.ru/3.6/library/pickle.html#pickle.HIGHEST_PROTOCOL). В настоящее время протоколом по умолчанию является 3 – новый протокол, разработанный для Python 3.7980Модуль [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle) предоставляет следующие функции для упрощения процесса упаковки:8182#### `pickle.dump(obj, file, protocol=None, *, fix_imports=True)`8384Записывает представление *obj* в виде pickle в открытый [объект файла](https://python-all.ru/3.6/glossary.html#term-file-object) *file*. Это эквивалентно `Pickler(file, protocol).dump(obj)`.8586Необязательный аргумент *протокол* – целое число, указывает упаковщику использовать заданный протокол; поддерживаются протоколы от 0 до [`HIGHEST_PROTOCOL`](https://python-all.ru/3.6/library/pickle.html#pickle.HIGHEST_PROTOCOL). Если аргумент не указан, по умолчанию используется [`DEFAULT_PROTOCOL`](https://python-all.ru/3.6/library/pickle.html#pickle.DEFAULT_PROTOCOL). Если указано отрицательное число, выбирается [`HIGHEST_PROTOCOL`](https://python-all.ru/3.6/library/pickle.html#pickle.HIGHEST_PROTOCOL).8788Аргумент *file* должен иметь метод write(), принимающий единственный аргумент типа bytes. Таким образом, это может быть файл на диске, открытый для двоичной записи, экземпляр [`io.BytesIO`](https://python-all.ru/3.6/library/io.html#io.BytesIO) или любой другой пользовательский объект, соответствующий этому интерфейсу.8990Если *fix\_imports* равен true и *протокол* меньше 3, pickle попытается сопоставить новые имена Python 3 со старыми именами модулей, используемыми в Python 2, чтобы поток данных pickle был читаем в Python 2.9192#### `pickle.dumps(obj, protocol=None, *, fix_imports=True)`9394Возвращает представление объекта в виде pickle в виде объекта [`bytes`](https://python-all.ru/3.6/library/stdtypes.html#bytes), вместо записи в файл.9596Аргументы *протокол* и *fix\_imports* имеют тот же смысл, что и в [`dump()`](https://python-all.ru/3.6/library/pickle.html#pickle.dump).9798#### `pickle.load(file, *, fix_imports=True, encoding="ASCII", errors="strict")`99100Читает представление объекта в pickle из открытого [объекта файла](https://python-all.ru/3.6/glossary.html#term-file-object) *file* и возвращает восстановленную иерархию объектов, указанную в нём. Это эквивалентно `Unpickler(file).load()`.101102Версия протокола pickle определяется автоматически, поэтому аргумент протокол не требуется. Байты, следующие за представлением объекта в pickle, игнорируются.103104Аргумент *file* должен иметь два метода: read(), принимающий целочисленный аргумент, и readline(), не требующий аргументов. Оба метода должны возвращать bytes. Таким образом, *file* может быть файловым объектом на диске, открытым для двоичного чтения, объектом [`io.BytesIO`](https://python-all.ru/3.6/library/io.html#io.BytesIO) или любым другим пользовательским объектом, соответствующим этому интерфейсу.105106Необязательными ключевыми аргументами являются *fix\_imports*, *encoding* и *errors*, которые используются для управления поддержкой совместимости с потоком pickle, созданным Python 2. Если *fix\_imports* равен true, pickle попытается сопоставить старые имена Python 2 с новыми именами, используемыми в Python 3. Аргументы *encoding* и *errors* указывают pickle, как декодировать 8-битные строковые экземпляры, сериализованные Python 2; по умолчанию они равны 'ASCII' и 'strict' соответственно. Аргумент *encoding* может быть равен 'bytes', чтобы читать эти 8-битные строковые экземпляры как объекты bytes. Использование `encoding='latin1'` необходимо для десериализации массивов NumPy и экземпляров [`datetime`](https://python-all.ru/3.6/library/datetime.html#datetime.datetime), [`date`](https://python-all.ru/3.6/library/datetime.html#datetime.date) и [`time`](https://python-all.ru/3.6/library/datetime.html#datetime.time), сериализованных Python 2.107108#### `pickle.loads(bytes_object, *, fix_imports=True, encoding="ASCII", errors="strict")`109110Читает иерархию объектов в pickle из объекта [`bytes`](https://python-all.ru/3.6/library/stdtypes.html#bytes) и возвращает восстановленную иерархию объектов, указанную в нём.111112Версия протокола pickle определяется автоматически, поэтому аргумент протокол не требуется. Байты, следующие за представлением объекта в pickle, игнорируются.113114Необязательными ключевыми аргументами являются *fix\_imports*, *encoding* и *errors*, которые используются для управления поддержкой совместимости с потоком pickle, созданным Python 2. Если *fix\_imports* равен true, pickle попытается сопоставить старые имена Python 2 с новыми именами, используемыми в Python 3. Аргументы *encoding* и *errors* указывают pickle, как декодировать 8-битные строковые экземпляры, сериализованные Python 2; по умолчанию они равны 'ASCII' и 'strict' соответственно. Аргумент *encoding* может быть равен 'bytes', чтобы читать эти 8-битные строковые экземпляры как объекты bytes. Использование `encoding='latin1'` необходимо для десериализации массивов NumPy и экземпляров [`datetime`](https://python-all.ru/3.6/library/datetime.html#datetime.datetime), [`date`](https://python-all.ru/3.6/library/datetime.html#datetime.date) и [`time`](https://python-all.ru/3.6/library/datetime.html#datetime.time), сериализованных Python 2.115116Модуль [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle) определяет три исключения:117118#### `exception pickle.PickleError`119120Общий базовый класс для других исключений pickle. Наследует [`Exception`](https://python-all.ru/3.6/library/exceptions.html#Exception).121122#### `exception pickle.PicklingError`123124Ошибка, возникающая, когда [`Pickler`](https://python-all.ru/3.6/library/pickle.html#pickle.Pickler) встречает неупаковываемый объект. Наследует [`PickleError`](https://python-all.ru/3.6/library/pickle.html#pickle.PickleError).125126Обратитесь к разделу [Какие объекты можно упаковывать и распаковывать?](https://python-all.ru/3.6/library/pickle.html#pickle-picklable), чтобы узнать, какие объекты можно упаковывать.127128#### `exception pickle.UnpicklingError`129130Ошибка, возникающая при проблемах распаковки объекта, например, из-за повреждения данных или нарушения безопасности. Наследует [`PickleError`](https://python-all.ru/3.6/library/pickle.html#pickle.PickleError).131132Обратите внимание, что во время распаковки могут возбуждаться и другие исключения, включая (но не ограничиваясь) AttributeError, EOFError, ImportError и IndexError.133134Модуль [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle) экспортирует два класса: [`Pickler`](https://python-all.ru/3.6/library/pickle.html#pickle.Pickler) и [`Unpickler`](https://python-all.ru/3.6/library/pickle.html#pickle.Unpickler):135136#### `class pickle.Pickler(file, protocol=None, *, fix_imports=True)`137138Он принимает двоичный файл для записи потока данных pickle.139140Необязательный аргумент *протокол* – целое число, указывает упаковщику использовать заданный протокол; поддерживаются протоколы от 0 до [`HIGHEST_PROTOCOL`](https://python-all.ru/3.6/library/pickle.html#pickle.HIGHEST_PROTOCOL). Если аргумент не указан, по умолчанию используется [`DEFAULT_PROTOCOL`](https://python-all.ru/3.6/library/pickle.html#pickle.DEFAULT_PROTOCOL). Если указано отрицательное число, выбирается [`HIGHEST_PROTOCOL`](https://python-all.ru/3.6/library/pickle.html#pickle.HIGHEST_PROTOCOL).141142Аргумент *file* должен иметь метод write(), принимающий единственный аргумент типа bytes. Таким образом, это может быть файл на диске, открытый для двоичной записи, экземпляр [`io.BytesIO`](https://python-all.ru/3.6/library/io.html#io.BytesIO) или любой другой пользовательский объект, соответствующий этому интерфейсу.143144Если *fix\_imports* равен true и *протокол* меньше 3, pickle попытается сопоставить новые имена Python 3 со старыми именами модулей, используемыми в Python 2, чтобы поток данных pickle был читаем в Python 2.145146#### `dump(obj)`147148Записывает представление *obj* в виде pickle в открытый объект файла, переданный в конструкторе.149150#### `persistent_id(obj)`151152По умолчанию ничего не делает. Этот метод существует, чтобы подкласс мог его переопределить.153154Если [`persistent_id()`](https://python-all.ru/3.6/library/pickle.html#pickle.Pickler.persistent_id) возвращает `None`, *obj* упаковывается как обычно. Любое другое значение заставляет [`Pickler`](https://python-all.ru/3.6/library/pickle.html#pickle.Pickler) выдать возвращённое значение в качестве постоянного идентификатора для *obj*. Значение этого постоянного идентификатора должно быть определено [`Unpickler.persistent_load()`](https://python-all.ru/3.6/library/pickle.html#pickle.Unpickler.persistent_load). Обратите внимание, что значение, возвращаемое [`persistent_id()`](https://python-all.ru/3.6/library/pickle.html#pickle.Pickler.persistent_id), само не может иметь постоянного идентификатора.155156См. [Постоянство внешних объектов](https://python-all.ru/3.6/library/pickle.html#pickle-persistent) для подробностей и примеров использования.157158#### `dispatch_table`159160Таблица диспетчеризации (dispatch table) объекта Pickler – это реестр *функций приведения (reduction functions)*, которые можно объявить с помощью [`copyreg.pickle()`](https://python-all.ru/3.6/library/copyreg.html#copyreg.pickle). Это отображение, где ключами являются классы, а значениями – функции приведения. Функция приведения принимает единственный аргумент соответствующего класса и должна соответствовать тому же интерфейсу, что и метод [`__reduce__()`](https://python-all.ru/3.6/library/pickle.html#object.__reduce__).161162По умолчанию объект Pickler не имеет атрибута [`dispatch_table`](https://python-all.ru/3.6/library/pickle.html#pickle.Pickler.dispatch_table), а вместо этого использует глобальную таблицу диспетчеризации, управляемую модулем [`copyreg`](https://python-all.ru/3.6/library/copyreg.html#module-copyreg). Однако для настройки упаковки для конкретного объекта Pickler можно задать атрибут [`dispatch_table`](https://python-all.ru/3.6/library/pickle.html#pickle.Pickler.dispatch_table) как объект, похожий на словарь. Кроме того, если подкласс [`Pickler`](https://python-all.ru/3.6/library/pickle.html#pickle.Pickler) имеет атрибут [`dispatch_table`](https://python-all.ru/3.6/library/pickle.html#pickle.Pickler.dispatch_table), то он будет использоваться в качестве таблицы диспетчеризации по умолчанию для экземпляров этого класса.163164См. [Таблицы диспетчеризации](https://python-all.ru/3.6/library/pickle.html#pickle-dispatch) в качестве примеров использования.165166Новое в версии 3.3.167168#### `fast`169170Устарело. Включает быстрый режим, если установлено в истинное значение. Быстрый режим отключает использование мемо, ускоряя процесс упаковки за счёт отсутствия лишних op-кодов PUT. Не следует использовать с самореферентными объектами, иначе [`Pickler`](https://python-all.ru/3.6/library/pickle.html#pickle.Pickler) будет рекурсивно вызывать себя до бесконечности.171172Используйте [`pickletools.optimize()`](https://python-all.ru/3.6/library/pickletools.html#pickletools.optimize), если нужны более компактные упаковки.173174#### `class pickle.Unpickler(file, *, fix_imports=True, encoding="ASCII", errors="strict")`175176Принимает бинарный файл для чтения потока данных pickle.177178Версия протокола pickle определяется автоматически, поэтому аргумент протокола не нужен.179180Аргумент *file* должен иметь два метода: read() с целочисленным аргументом и readline() без аргументов. Оба метода должны возвращать bytes. Таким образом, *file* может быть файловым объектом на диске, открытым для двоичного чтения, объектом [`io.BytesIO`](https://python-all.ru/3.6/library/io.html#io.BytesIO) или любым другим пользовательским объектом, соответствующим этому интерфейсу.181182Необязательными ключевыми аргументами являются *fix\_imports*, *encoding* и *errors*, которые используются для управления поддержкой совместимости с потоком pickle, созданным Python 2. Если *fix\_imports* равен true, pickle попытается сопоставить старые имена Python 2 с новыми именами, используемыми в Python 3. Аргументы *encoding* и *errors* указывают pickle, как декодировать 8-битные строковые экземпляры, сериализованные Python 2; по умолчанию они равны 'ASCII' и 'strict' соответственно. Аргумент *encoding* может быть равен 'bytes', чтобы читать эти 8-битные строковые экземпляры как объекты bytes.183184#### `load()`185186Читает представление объекта в pickle из открытого объекта файла, переданного в конструкторе, и возвращает восстановленную иерархию объектов, указанную в нём. Байты, следующие за представлением объекта в pickle, игнорируются.187188#### `persistent_load(pid)`189190По умолчанию вызывает [`UnpicklingError`](https://python-all.ru/3.6/library/pickle.html#pickle.UnpicklingError).191192Если определено, [`persistent_load()`](https://python-all.ru/3.6/library/pickle.html#pickle.Unpickler.persistent_load) должен возвращать объект, указанный постоянным идентификатором *pid*. Если встречен недопустимый постоянный идентификатор, должно быть вызвано [`UnpicklingError`](https://python-all.ru/3.6/library/pickle.html#pickle.UnpicklingError).193194См. [Постоянство внешних объектов](https://python-all.ru/3.6/library/pickle.html#pickle-persistent) для подробностей и примеров использования.195196#### `find_class(module, name)`197198Импортирует *module* при необходимости и возвращает объект с именем *name* из него, где аргументы *module* и *name* являются объектами [`str`](https://python-all.ru/3.6/library/stdtypes.html#str). Обратите внимание: вопреки названию, [`find_class()`](https://python-all.ru/3.6/library/pickle.html#pickle.Unpickler.find_class) также используется для поиска функций.199200Подклассы могут переопределить этот метод для получения контроля над тем, объекты какого типа и каким образом могут быть загружены, что потенциально снижает риски безопасности. См. [Ограничение глобальных объектов](https://python-all.ru/3.6/library/pickle.html#pickle-restrict) для подробностей.201202## 12.1.4. Что можно упаковать и распаковать с помощью pickle?203204Следующие типы можно сериализовать:205206- `None`, `True` и `False`207- целые числа, числа с плавающей запятой, комплексные числа208- строки, байты, байтовые массивы209- кортежи, списки, множества и словари, содержащие только сериализуемые объекты210- функции, определённые на верхнем уровне модуля (с помощью [`def`](https://python-all.ru/3.6/reference/compound_stmts.html#def), а не [`lambda`](https://python-all.ru/3.6/reference/expressions.html#lambda))211- встроенные функции, определённые на верхнем уровне модуля212- классы, определённые на верхнем уровне модуля213- экземпляры таких классов, чей [`__dict__`](https://python-all.ru/3.6/library/stdtypes.html#object.__dict__) или результат вызова [`__getstate__()`](https://python-all.ru/3.6/library/pickle.html#object.__getstate__) можно упаковать (см. раздел [Упаковка экземпляров классов](https://python-all.ru/3.6/library/pickle.html#pickle-inst) для подробностей).214215Попытки сериализовать несериализуемые объекты приведут к возникновению исключения [`PicklingError`](https://python-all.ru/3.6/library/pickle.html#pickle.PicklingError); при этом на диск может быть уже записано неизвестное количество байтов. Попытка сериализовать сильно рекурсивную структуру данных может превысить максимальную глубину рекурсии – в этом случае будет возбуждено [`RecursionError`](https://python-all.ru/3.6/library/exceptions.html#RecursionError). Можно аккуратно увеличить этот лимит с помощью [`sys.setrecursionlimit()`](https://python-all.ru/3.6/library/sys.html#sys.setrecursionlimit).216217Обратите внимание, что функции (встроенные и определённые пользователем) сериализуются по «полному» имени, а не по значению. [2](https://python-all.ru/3.6/library/pickle.html#id7) Это означает, что сериализуется только имя функции вместе с именем модуля, в котором она определена. Ни код функции, ни её атрибуты не сериализуются. Таким образом, определяющий модуль должен быть импортируем в среде десериализации, и модуль должен содержать именованный объект, иначе будет возбуждено исключение. [3](https://python-all.ru/3.6/library/pickle.html#id8)218219Аналогично, классы сериализуются по именованной ссылке, поэтому в среде десериализации действуют те же ограничения. Обратите внимание, что ни код класса, ни его данные не сериализуются, поэтому в следующем примере атрибут класса `attr` не восстанавливается в среде десериализации:220221```python222class Foo:223 attr = 'A class attribute'224225picklestring = pickle.dumps(Foo)226```227228Эти ограничения объясняют, почему сериализуемые функции и классы должны быть определены на верхнем уровне модуля.229230Аналогично, при сериализации экземпляров классов код и данные самого класса не сериализуются вместе с ними. Сериализуются только данные экземпляра. Это сделано намеренно, чтобы можно было исправить ошибки в классе или добавить в него методы и по-прежнему загружать объекты, созданные с помощью более старой версии класса. Если планируется использовать долгоживущие объекты, которые переживут множество версий класса, будет разумно добавить в объекты номер версии, чтобы можно было выполнять соответствующие преобразования с помощью метода [`__setstate__()`](https://python-all.ru/3.6/library/pickle.html#object.__setstate__) класса.231232## 12.1.5. Упаковка экземпляров классов233234В этом разделе описываются общие механизмы, позволяющие определять, настраивать и контролировать процесс сериализации и десериализации экземпляров классов.235236В большинстве случаев для того, чтобы экземпляры стали сериализуемыми, не требуется дополнительного кода. По умолчанию pickle получает класс и атрибуты экземпляра через интроспекцию. При десериализации экземпляра класса его метод [`__init__()`](https://python-all.ru/3.6/reference/datamodel.html#object.__init__) обычно *не* вызывается. Поведение по умолчанию сначала создаёт неинициализированный экземпляр, а затем восстанавливает сохранённые атрибуты. Следующий код демонстрирует реализацию такого поведения:237238```python239def save(obj):240 return (obj.__class__, obj.__dict__)241242def load(cls, attributes):243 obj = cls.__new__(cls)244 obj.__dict__.update(attributes)245 return obj246```247248Классы могут изменить поведение по умолчанию, предоставив один или несколько специальных методов:249250#### `object.__getnewargs_ex__()`251252В протоколах 2 и выше классы, реализующие метод [`__getnewargs_ex__()`](https://python-all.ru/3.6/library/pickle.html#object.__getnewargs_ex__), могут задавать значения, передаваемые методу [`__new__()`](https://python-all.ru/3.6/reference/datamodel.html#object.__new__) при распаковке. Метод должен возвращать пару `(args, kwargs)`, где *args* – кортеж позиционных аргументов, а *kwargs* – словарь именованных аргументов для конструирования объекта. Эти значения будут переданы методу [`__new__()`](https://python-all.ru/3.6/reference/datamodel.html#object.__new__) при распаковке.253254Этот метод следует реализовать, если метод [`__new__()`](https://python-all.ru/3.6/reference/datamodel.html#object.__new__) вашего класса требует только именованных аргументов (keyword-only). В противном случае для обеспечения совместимости рекомендуется реализовать [`__getnewargs__()`](https://python-all.ru/3.6/library/pickle.html#object.__getnewargs__).255256Изменено в версии 3.6: [`__getnewargs_ex__()`](https://python-all.ru/3.6/library/pickle.html#object.__getnewargs_ex__) теперь используется в протоколах 2 и 3.257258#### `object.__getnewargs__()`259260Этот метод служит той же цели, что и [`__getnewargs_ex__()`](https://python-all.ru/3.6/library/pickle.html#object.__getnewargs_ex__), но поддерживает только позиционные аргументы. Он должен возвращать кортеж аргументов `args`, который будет передан методу [`__new__()`](https://python-all.ru/3.6/reference/datamodel.html#object.__new__) при десериализации.261262[`__getnewargs__()`](https://python-all.ru/3.6/library/pickle.html#object.__getnewargs__) не будет вызываться, если определён [`__getnewargs_ex__()`](https://python-all.ru/3.6/library/pickle.html#object.__getnewargs_ex__).263264Изменено в версии 3.6: До Python 3.6 в протоколах 2 и 3 вместо [`__getnewargs_ex__()`](https://python-all.ru/3.6/library/pickle.html#object.__getnewargs_ex__) вызывался [`__getnewargs__()`](https://python-all.ru/3.6/library/pickle.html#object.__getnewargs__).265266#### `object.__getstate__()`267268Классы могут дополнительно влиять на то, как упаковываются их экземпляры: если класс определяет метод [`__getstate__()`](https://python-all.ru/3.6/library/pickle.html#object.__getstate__), он вызывается, и возвращаемый объект упаковывается как содержимое экземпляра вместо содержимого его словаря. Если метод [`__getstate__()`](https://python-all.ru/3.6/library/pickle.html#object.__getstate__) отсутствует, [`__dict__`](https://python-all.ru/3.6/library/stdtypes.html#object.__dict__) экземпляра упаковывается как обычно.269270#### `object.__setstate__(state)`271272При распаковке, если класс определяет [`__setstate__()`](https://python-all.ru/3.6/library/pickle.html#object.__setstate__), он вызывается с распакованным состоянием. В этом случае нет требования, чтобы объект состояния был словарём. В противном случае упакованное состояние должно быть словарём, и его элементы присваиваются словарю нового экземпляра.273274> **Примечание**275>276> Если [`__getstate__()`](https://python-all.ru/3.6/library/pickle.html#object.__getstate__) возвращает ложное значение, метод [`__setstate__()`](https://python-all.ru/3.6/library/pickle.html#object.__setstate__) не будет вызван при распаковке.277278Обратитесь к разделу [Обработка объектов с состоянием](https://python-all.ru/3.6/library/pickle.html#pickle-state) за дополнительной информацией о том, как использовать методы [`__getstate__()`](https://python-all.ru/3.6/library/pickle.html#object.__getstate__) и [`__setstate__()`](https://python-all.ru/3.6/library/pickle.html#object.__setstate__).279280> **Примечание**281>282> При распаковке могут быть вызваны некоторые методы экземпляра, такие как [`__getattr__()`](https://python-all.ru/3.6/reference/datamodel.html#object.__getattr__), [`__getattribute__()`](https://python-all.ru/3.6/reference/datamodel.html#object.__getattribute__) или [`__setattr__()`](https://python-all.ru/3.6/reference/datamodel.html#object.__setattr__). Если эти методы полагаются на соблюдение некоторого внутреннего инварианта, тип должен реализовать [`__getnewargs__()`](https://python-all.ru/3.6/library/pickle.html#object.__getnewargs__) или [`__getnewargs_ex__()`](https://python-all.ru/3.6/library/pickle.html#object.__getnewargs_ex__) для установления такого инварианта; в противном случае ни [`__new__()`](https://python-all.ru/3.6/reference/datamodel.html#object.__new__), ни [`__init__()`](https://python-all.ru/3.6/reference/datamodel.html#object.__init__) не будут вызваны.283284Как мы увидим, pickle не использует напрямую описанные выше методы. На самом деле эти методы являются частью протокола копирования, который реализует специальный метод [`__reduce__()`](https://python-all.ru/3.6/library/pickle.html#object.__reduce__). Протокол копирования предоставляет единый интерфейс для получения данных, необходимых для упаковки и копирования объектов. [4](https://python-all.ru/3.6/library/pickle.html#id9)285286Хотя реализация [`__reduce__()`](https://python-all.ru/3.6/library/pickle.html#object.__reduce__) непосредственно в классах является мощной, она чревата ошибками. По этой причине разработчикам классов следует использовать высокоуровневый интерфейс (т.е. [`__getnewargs_ex__()`](https://python-all.ru/3.6/library/pickle.html#object.__getnewargs_ex__), [`__getstate__()`](https://python-all.ru/3.6/library/pickle.html#object.__getstate__) и [`__setstate__()`](https://python-all.ru/3.6/library/pickle.html#object.__setstate__)), когда это возможно. Однако мы покажем случаи, когда использование [`__reduce__()`](https://python-all.ru/3.6/library/pickle.html#object.__reduce__) является единственным вариантом или приводит к более эффективной упаковке, или и то и другое.287288#### `object.__reduce__()`289290В настоящее время интерфейс определён следующим образом. Метод [`__reduce__()`](https://python-all.ru/3.6/library/pickle.html#object.__reduce__) не принимает аргументов и должен возвращать либо строку, либо, желательно, кортеж (возвращаемый объект часто называют «reduce value»).291292Если возвращается строка, она должна интерпретироваться как имя глобальной переменной. Это должно быть локальное имя объекта относительно его модуля; модуль pickle ищет объект в пространстве имён модуля. Такое поведение обычно полезно для одиночек (singletons).293294Если возвращается кортеж, он должен содержать от двух до пяти элементов. Необязательные элементы можно опустить или указать `None` в качестве их значения. Семантика каждого элемента по порядку:295296- Вызываемый объект, который будет вызван для создания начальной версии объекта.297- Кортеж аргументов для вызываемого объекта. Если вызываемый объект не принимает ни одного аргумента, должен быть передан пустой кортеж.298- Необязательно: состояние объекта, которое будет передано методу [`__setstate__()`](https://python-all.ru/3.6/library/pickle.html#object.__setstate__) объекта, как описано ранее. Если у объекта нет такого метода, то значение должно быть словарём, и оно будет добавлено в атрибут [`__dict__`](https://python-all.ru/3.6/library/stdtypes.html#object.__dict__) объекта.299- Необязательно, итератор (а не последовательность), выдающий последовательные элементы. Эти элементы будут добавлены к объекту либо с помощью `obj.append(item)`, либо пакетно с помощью `obj.extend(list_of_items)`. В основном используется для подклассов списка, но может использоваться и другими классами, если у них есть методы `append()` и `extend()` с подходящей сигнатурой. (То, используется ли `append()` или `extend()`, зависит от используемой версии протокола pickle и количества добавляемых элементов, поэтому оба должны поддерживаться.)300- Необязательно: итератор (не последовательность), возвращающий последовательные пары ключ-значение. Эти элементы будут сохранены в объекте с помощью `obj[key] = value`. В основном это используется для подклассов словаря, но может использоваться и другими классами, если они реализуют [`__setitem__()`](https://python-all.ru/3.6/reference/datamodel.html#object.__setitem__).301302#### `object.__reduce_ex__(protocol)`303304В качестве альтернативы может быть определён метод [`__reduce_ex__()`](https://python-all.ru/3.6/library/pickle.html#object.__reduce_ex__). Единственное отличие состоит в том, что этот метод должен принимать один целочисленный аргумент – версию протокола. Если он определён, pickle будет предпочитать его методу [`__reduce__()`](https://python-all.ru/3.6/library/pickle.html#object.__reduce__). Кроме того, [`__reduce__()`](https://python-all.ru/3.6/library/pickle.html#object.__reduce__) автоматически становится синонимом расширенной версии. Основное назначение этого метода – предоставлять обратно совместимые reduce-значения для старых версий Python.305306### 12.1.5.1. Постоянство внешних объектов307308Для обеспечения персистентности объектов модуль [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle) поддерживает понятие ссылки на объект вне упакованного потока данных. Такие объекты идентифицируются по постоянному идентификатору (persistent ID), который должен быть либо строкой из буквенно-цифровых символов (для протокола 0), [5](https://python-all.ru/3.6/library/pickle.html#id10) либо просто произвольным объектом (для любого более нового протокола).309310Разрешение таких постоянных идентификаторов не определяется модулем [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle); оно делегируется определённым пользователем методам на pickler и unpickler: [`persistent_id()`](https://python-all.ru/3.6/library/pickle.html#pickle.Pickler.persistent_id) и [`persistent_load()`](https://python-all.ru/3.6/library/pickle.html#pickle.Unpickler.persistent_load) соответственно.311312Для упаковки объектов, имеющих внешний постоянный идентификатор, упаковщик должен иметь пользовательский метод [`persistent_id()`](https://python-all.ru/3.6/library/pickle.html#pickle.Pickler.persistent_id), который принимает объект в качестве аргумента и возвращает либо `None`, либо постоянный идентификатор для этого объекта. Если возвращается `None`, упаковщик просто упаковывает объект обычным образом. Если возвращается строка постоянного идентификатора, упаковщик упаковывает этот объект, вместе с маркером, чтобы распаковщик распознал его как постоянный идентификатор.313314Чтобы распаковать внешние объекты, распаковщик должен иметь пользовательский метод [`persistent_load()`](https://python-all.ru/3.6/library/pickle.html#pickle.Unpickler.persistent_load), который принимает объект постоянного идентификатора и возвращает ссылочный объект.315316Вот исчерпывающий пример, показывающий, как постоянный идентификатор может использоваться для упаковки внешних объектов по ссылке.317318```python319# Простой пример, показывающий, как с помощью persistent ID можно упаковать внешние объекты по ссылке.320# внешние объекты по ссылке.321322import pickle323import sqlite3324from collections import namedtuple325326# Простой класс, представляющий запись в нашей базе данных.327MemoRecord = namedtuple("MemoRecord", "key, task")328329class DBPickler(pickle.Pickler):330331 def persistent_id(self, obj):332 # Вместо упаковки MemoRecord как обычного экземпляра класса, мы выводим333 # постоянный идентификатор.334 if isinstance(obj, MemoRecord):335 # Здесь наш постоянный идентификатор – это просто кортеж, содержащий метку и ключ, который ссылается на определённую запись в базе данных.336 # ключ, который ссылается на определённую запись в базе данных.337 return ("MemoRecord", obj.key)338 else:339 # Этот метод вызывается при каждом обнаружении постоянного идентификатора.340 # требуется упаковать как обычно.341 return None342343class DBUnpickler(pickle.Unpickler):344345 def __init__(self, file, connection):346 super().__init__(file)347 self.connection = connection348349 def persistent_load(self, pid):350 # Извлеките запись из базы данных по ссылке и верните её.351 # Всегда возбуждает исключение, если невозможно вернуть правильный объект.352 cursor = self.connection.cursor()353 type_tag, key_id = pid354 if type_tag == "MemoRecord":355 # Извлеките указанную запись из базы данных и верните её.356 cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),))357 key, task = cursor.fetchone()358 return MemoRecord(key, task)359 else:360 # Инициализируйте и наполните базу данных.361 # Извлеките записи для упаковки.362 # по постоянному идентификатору.363 raise pickle.UnpicklingError("unsupported persistent object")364365def main():366 import io367 import pprint368369 # Обновите запись для надёжности.370 conn = sqlite3.connect(":memory:")371 cursor = conn.cursor()372 cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)")373 tasks = (374 'give food to fish',375 'prepare group meeting',376 'fight with a zebra',377 )378 for task in tasks:379 cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,))380381 # Извлеките записи, которые требуется упаковать.382 cursor.execute("SELECT * FROM memos")383 memos = [MemoRecord(key, task) for key, task in cursor]384 # Выводит и нумерует строки в текстовом файле.385 file = io.BytesIO()386 DBPickler(file).dump(memos)387388 print("Pickled records:")389 pprint.pprint(memos)390391 # Обновите запись, для верности.392 cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1")393394 # Удаляет не подлежащие упаковке записи.395 file.seek(0)396 memos = DBUnpickler(file, conn).load()397398 print("Unpickled records:")399 pprint.pprint(memos)400401if __name__ == '__main__':402 main()403```404405### 12.1.5.2. Таблицы диспетчеризации406407Если требуется настроить упаковку некоторых классов, не затрагивая другой код, зависящий от упаковки, можно создать упаковщик с частной диспетчерской таблицей.408409Глобальная диспетчерская таблица, управляемая модулем [`copyreg`](https://python-all.ru/3.6/library/copyreg.html#module-copyreg), доступна как `copyreg.dispatch_table`. Поэтому можно использовать модифицированную копию `copyreg.dispatch_table` в качестве частной диспетчерской таблицы.410411Например412413```python414f = io.BytesIO()415p = pickle.Pickler(f)416p.dispatch_table = copyreg.dispatch_table.copy()417p.dispatch_table[SomeClass] = reduce_SomeClass418```419420создаёт экземпляр [`pickle.Pickler`](https://python-all.ru/3.6/library/pickle.html#pickle.Pickler) с частной диспетчерской таблицей, которая обрабатывает класс `SomeClass` особым образом. В качестве альтернативы код421422```python423class MyPickler(pickle.Pickler):424 dispatch_table = copyreg.dispatch_table.copy()425 dispatch_table[SomeClass] = reduce_SomeClass426f = io.BytesIO()427p = MyPickler(f)428```429430делает то же самое, но все экземпляры `MyPickler` по умолчанию используют одну и ту же таблицу диспетчеризации. Эквивалентный код с использованием модуля [`copyreg`](https://python-all.ru/3.6/library/copyreg.html#module-copyreg):431432```python433copyreg.pickle(SomeClass, reduce_SomeClass)434f = io.BytesIO()435p = pickle.Pickler(f)436```437438### 12.1.5.3. Обработка объектов с состоянием439440Вот пример, показывающий, как изменить поведение упаковки для класса. Класс `TextReader` открывает текстовый файл и возвращает номер строки и её содержимое каждый раз, когда вызывается его метод `readline()`. Если экземпляр `TextReader` упаковывается, сохраняются все атрибуты, *кроме* элемента-файлового объекта. Когда экземпляр распаковывается, файл открывается заново, и чтение продолжается с последней позиции. Методы [`__setstate__()`](https://python-all.ru/3.6/library/pickle.html#object.__setstate__) и [`__getstate__()`](https://python-all.ru/3.6/library/pickle.html#object.__getstate__) используются для реализации такого поведения.441442```python443class TextReader:444 """Вывести и пронумеровать строки в текстовом файле."""445446 def __init__(self, filename):447 self.filename = filename448 self.file = open(filename)449 self.lineno = 0450451 def readline(self):452 self.lineno += 1453 line = self.file.readline()454 if not line:455 return None456 if line.endswith('\n'):457 line = line[:-1]458 return "%i: %s" % (self.lineno, line)459460 def __getstate__(self):461 # Восстанавливает состояние ранее открытого файла. Для этого необходимо открыть его заново и читать, пока не будет восстановлено количество строк.462 # Наконец, сохраняет файл.463 # метод, чтобы избежать изменения исходного состояния.464 state = self.__dict__.copy()465 # Для любого другого объекта используйте обычную редукцию.466 del state['file']467 return state468469 def __setstate__(self, state):470 # Восстановить атрибуты экземпляра (например, filename и lineno).471 self.__dict__.update(state)472 # Получить дескриптор исходного буферного объекта.473 # открыть его заново и читать, пока количество строк не восстановится.474 file = open(self.filename)475 for _ in range(self.lineno):476 file.readline()477 # Наконец, сохраните файл.478 self.file = file479```480481Пример использования может выглядеть так:482483```python484>>> reader = TextReader("hello.txt")485>>> reader.readline()486'1: Hello world!'487>>> reader.readline()488'2: I am line number two.'489>>> new_reader = pickle.loads(pickle.dumps(reader))490>>> new_reader.readline()491'3: Goodbye!'492```493494## 12.1.6. Ограничение глобальных объектов495496По умолчанию распаковщик импортирует любой класс или функцию, найденные в данных pickle. Для многих приложений такое поведение неприемлемо, поскольку оно позволяет распаковщику импортировать и вызывать произвольный код. Просто подумайте, что делает этот вручную созданный поток данных pickle при загрузке:497498```python499>>> import pickle500>>> pickle.loads(b"cos\nsystem\n(S'echo hello world'\ntR.")501hello world5020503```504505В этом примере распаковщик импортирует функцию [`os.system()`](https://python-all.ru/3.6/library/os.html#os.system), а затем применяет строковый аргумент «echo hello world». Хотя этот пример безобиден, нетрудно представить такой, который может нанести вред вашей системе.506507По этой причине может потребоваться контролировать, что распаковывается, с помощью настройки [`Unpickler.find_class()`](https://python-all.ru/3.6/library/pickle.html#pickle.Unpickler.find_class). Вопреки своему названию, [`Unpickler.find_class()`](https://python-all.ru/3.6/library/pickle.html#pickle.Unpickler.find_class) вызывается всякий раз, когда запрашивается глобальный объект (т.е. класс или функция). Таким образом, можно либо полностью запретить глобалы, либо ограничить их безопасным подмножеством.508509Вот пример распаковщика, который разрешает загрузку только нескольких безопасных классов из модуля [`builtins`](https://python-all.ru/3.6/library/builtins.html#module-builtins):510511```python512import builtins513import io514import pickle515516safe_builtins = {517 'range',518 'complex',519 'set',520 'frozenset',521 'slice',522}523524class RestrictedUnpickler(pickle.Unpickler):525526 def find_class(self, module, name):527 # Разрешать только безопасные классы из builtins.528 if module == "builtins" and name in safe_builtins:529 return getattr(builtins, name)530 # Запрещать всё остальное.531 raise pickle.UnpicklingError("global '%s.%s' is forbidden" %532 (module, name))533534def restricted_loads(s):535 """Вспомогательная функция, аналогичная pickle.loads()."""536 return RestrictedUnpickler(io.BytesIO(s)).load()537```538539Пример использования нашего десериализатора, работающего как задумано:540541```python542>>> restricted_loads(pickle.dumps([1, 2, range(15)]))543[1, 2, range(0, 15)]544>>> restricted_loads(b"cos\nsystem\n(S'echo hello world'\ntR.")545Traceback (most recent call last):546 ...547pickle.UnpicklingError: global 'os.system' is forbidden548>>> restricted_loads(b'cbuiltins\neval\n'549... b'(S\'getattr(__import__("os"), "system")'550... b'("echo hello world")\'\ntR.')551Traceback (most recent call last):552 ...553pickle.UnpicklingError: global 'builtins.eval' is forbidden554```555556Как показывают наши примеры, нужно быть осторожным с тем, что разрешается распаковывать. Поэтому если безопасность важна, стоит рассмотреть альтернативы, такие как marshalling API в модуле [`xmlrpc.client`](https://python-all.ru/3.6/library/xmlrpc.client.html#module-xmlrpc.client) или сторонние решения.557558## 12.1.7. Производительность559560Последние версии протокола pickle (начиная с протокола 2) поддерживают эффективное бинарное кодирование для ряда распространённых возможностей и встроенных типов. Кроме того, модуль [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle) имеет прозрачный оптимизатор, написанный на C.561562## 12.1.8. Примеры563564Для простейшего кода используйте функции [`dump()`](https://python-all.ru/3.6/library/pickle.html#pickle.dump) и [`load()`](https://python-all.ru/3.6/library/pickle.html#pickle.load).565566```python567import pickle568569# Произвольный набор объектов, поддерживаемых pickle.570data = {571 'a': [1, 2.0, 3, 4+6j],572 'b': ("character string", b"byte string"),573 'c': {None, True, False}574}575576with open('data.pickle', 'wb') as f:577 # Запаковать словарь 'data', используя самый высокий доступный протокол.578 pickle.dump(data, f, pickle.HIGHEST_PROTOCOL)579```580581Следующий пример читает полученные сериализованные данные.582583```python584import pickle585586with open('data.pickle', 'rb') as f:587 # Версия используемого протокола определяется автоматически, поэтому588 # указывать её не нужно.589 data = pickle.load(f)590```591592> **См. также**593>594> **Модуль [`copyreg`](https://python-all.ru/3.6/library/copyreg.html#module-copyreg)**595>596> Регистрация конструктора интерфейса pickle для расширенных типов.597>598> **Модуль [`pickletools`](https://python-all.ru/3.6/library/pickletools.html#module-pickletools)**599>600> Инструменты для работы и анализа сериализованных данных.601>602> **Модуль [`shelve`](https://python-all.ru/3.6/library/shelve.html#module-shelve)**603>604> Индексированные базы данных объектов; использует [`pickle`](https://python-all.ru/3.6/library/pickle.html#module-pickle).605>606> **Модуль [`copy`](https://python-all.ru/3.6/library/copy.html#module-copy)**607>608> Поверхностное и глубокое копирование объектов.609>610> **Модуль [`marshal`](https://python-all.ru/3.6/library/marshal.html#module-marshal)**611>612> Высокопроизводительная сериализация встроенных типов.613614Сноски615616**[1](https://python-all.ru/3.6/library/pickle.html#id1)**617618Не путайте это с модулем [`marshal`](https://python-all.ru/3.6/library/marshal.html#module-marshal)619620**[2](https://python-all.ru/3.6/library/pickle.html#id2)**621622Вот почему функции [`lambda`](https://python-all.ru/3.6/reference/expressions.html#lambda) нельзя сериализовать: все функции [`lambda`](https://python-all.ru/3.6/reference/expressions.html#lambda) имеют одно и то же имя: `<lambda>`.623624**[3](https://python-all.ru/3.6/library/pickle.html#id3)**625626Возникающее исключение, скорее всего, будет [`ImportError`](https://python-all.ru/3.6/library/exceptions.html#ImportError) или [`AttributeError`](https://python-all.ru/3.6/library/exceptions.html#AttributeError), но может быть и другим.627628**[4](https://python-all.ru/3.6/library/pickle.html#id4)**629630Модуль [`copy`](https://python-all.ru/3.6/library/copy.html#module-copy) использует этот протокол для операций поверхностного и глубокого копирования.631632**[5](https://python-all.ru/3.6/library/pickle.html#id5)**633634Ограничение на алфавитно-цифровые символы связано с тем, что постоянные идентификаторы в протоколе 0 разделяются символом новой строки. Поэтому если в постоянных идентификаторах встречаются какие-либо символы новой строки, результирующий pickle станет нечитаемым.635