Документация Python неофициальный перевод

pickle.md

626 строк · 71.7 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.4/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.4/library/pickle.html#module-pickle) – сериализация объектов Python89Модуль [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle) реализует двоичные протоколы для сериализации и десериализации структуры объектов Python. *“Pickling”* – это процесс преобразования иерархии объектов Python в поток байтов, а *“unpickling”* – обратная операция, при которой поток байтов (из [*двоичного файла*](https://python-all.ru/3.4/glossary.html#term-binary-file) или [*байтоподобного объекта*](https://python-all.ru/3.4/glossary.html#term-bytes-like-object)) преобразуется обратно в иерархию объектов. Pickling (и unpickling) также называют «сериализацией», «маршалингом»[\[1\]](https://python-all.ru/3.4/library/pickle.html#id6) или «уплощением»; однако во избежание путаницы здесь используются термины «pickling» и «unpickling».1011> **Предупреждение**12>13> Модуль [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle) небезопасен при работе с ошибочными или вредоносными данными. Категорически запрещается десериализовать (unpickle) данные, полученные из ненадёжного или непроверенного источника.1415## 12.1.1. Взаимосвязь с другими модулями Python1617### 12.1.1.1. Сравнение с `marshal`1819В Python есть более примитивный модуль сериализации под названием [`marshal`](https://python-all.ru/3.4/library/marshal.html#module-marshal), но в целом [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle) всегда должен быть предпочтительным способом сериализации объектов Python. [`marshal`](https://python-all.ru/3.4/library/marshal.html#module-marshal) существует в основном для поддержки файлов `.pyc`.2021Модуль [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle) отличается от [`marshal`](https://python-all.ru/3.4/library/marshal.html#module-marshal) в нескольких важных аспектах:2223- Модуль [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle) отслеживает уже сериализованные объекты, чтобы последующие ссылки на тот же объект не сериализовались повторно. [`marshal`](https://python-all.ru/3.4/library/marshal.html#module-marshal) этого не делает.2425  Это имеет значение как для рекурсивных объектов, так и для совместного использования объектов. Рекурсивные объекты – это объекты, содержащие ссылки на самих себя. Они не обрабатываются модулем marshal; более того, попытка выполнить маршалинг рекурсивных объектов с помощью marshal приведёт к аварийному завершению интерпретатора Python. Совместное использование объектов возникает, когда на один и тот же объект есть несколько ссылок в разных местах сериализуемой иерархии. [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle) сохраняет такие объекты только один раз и гарантирует, что все остальные ссылки указывают на главную копию. Совместно используемые объекты остаются совместно используемыми, что может быть очень важно для изменяемых объектов.26- [`marshal`](https://python-all.ru/3.4/library/marshal.html#module-marshal) нельзя использовать для сериализации пользовательских классов и их экземпляров. [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle) может прозрачно сохранять и восстанавливать экземпляры классов, однако определение класса должно быть импортируемым и находиться в том же модуле, что и на момент сохранения объекта.27- Формат сериализации [`marshal`](https://python-all.ru/3.4/library/marshal.html#module-marshal) не гарантирует переносимости между версиями Python. Поскольку его основная задача – поддержка файлов `.pyc`, разработчики Python оставляют за собой право изменять формат сериализации способами, несовместимыми с предыдущими версиями, если возникнет необходимость. Формат сериализации [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle) гарантированно обратно совместим во всех выпусках Python.2829### 12.1.1.2. Сравнение с `json`3031Существуют принципиальные различия между протоколами pickle и [JSON (JavaScript Object Notation)](https://python-all.ru/3.4/library/pickle.html):3233- JSON – это текстовый формат сериализации (он выводит текст в Unicode, хотя в большинстве случаев затем кодируется в `utf-8`), в то время как pickle – это двоичный формат сериализации.34- JSON удобочитаем, а pickle – нет;35- JSON интероперабелен и широко используется за пределами экосистемы Python, тогда как pickle является специфичным для Python;36- JSON по умолчанию может представлять лишь подмножество встроенных типов Python и не поддерживает пользовательские классы; pickle же может представлять огромное количество типов Python (многие из них автоматически, благодаря умелому использованию средств интроспекции Python; сложные случаи можно решить, реализовав [*специальные объектные API*](https://python-all.ru/3.4/library/pickle.html#pickle-inst)).3738> **См. также**39>40> Модуль [`json`](https://python-all.ru/3.4/library/json.html#module-json): модуль стандартной библиотеки, позволяющий выполнять сериализацию и десериализацию JSON.4142## 12.1.2. Формат потока данных4344Формат данных, используемый [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle), является специфичным для Python. Преимущество в том, что нет ограничений, налагаемых внешними стандартами, такими как JSON или XDR (которые не могут представлять разделение указателей); однако это означает, что программы не на Python могут не смочь восстановить сериализованные с помощью pickle объекты Python.4546По умолчанию формат данных [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle) использует относительно компактное двоичное представление. Если требуется оптимальный размер, можно эффективно [*сжимать*](https://python-all.ru/3.4/library/archiving.html) сериализованные данные.4748Модуль [`pickletools`](https://python-all.ru/3.4/library/pickletools.html#module-pickletools) содержит инструменты для анализа потоков данных, создаваемых модулем [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle). Исходный код [`pickletools`](https://python-all.ru/3.4/library/pickletools.html#module-pickletools) содержит обширные комментарии о кодах операций, используемых протоколами pickle.4950В настоящее время существует 5 различных протоколов, которые можно использовать для сериализации. Чем выше используемый протокол, тем более новая версия Python требуется для чтения созданного pickle.5152- Протокол версии 0 – это исходный «человекочитаемый» протокол, обратно совместимый с более ранними версиями Python.53- Протокол версии 1 – это старый двоичный формат, также совместимый с более ранними версиями Python.54- Протокол версии 2 был представлен в Python 2.3. Он обеспечивает гораздо более эффективную сериализацию [*классов нового стиля*](https://python-all.ru/3.4/glossary.html#term-new-style-class). Дополнительную информацию об улучшениях, внесённых протоколом 2, см. в [**PEP 307**](https://python-all.ru/3.4/library/pickle.html).55- Версия протокола 3 была добавлена в Python 3.0. Она имеет явную поддержку объектов [`bytes`](https://python-all.ru/3.4/library/functions.html#bytes) и не может быть десериализована (unpickled) в Python 2.x. Это протокол по умолчанию и рекомендуемый протокол, когда требуется совместимость с другими версиями Python 3.56- Протокол версии 4 был добавлен в Python 3.4. Он добавляет поддержку очень больших объектов, сериализацию большего числа типов объектов и некоторые оптимизации формата данных. Обратитесь к [**PEP 3154**](https://python-all.ru/3.4/library/pickle.html) для получения информации об улучшениях, внесённых протоколом 4.5758> **Примечание**59>60> Сериализация – это более примитивное понятие, чем персистентность; хотя [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle) читает и записывает файловые объекты, он не решает проблему именования персистентных объектов, равно как и (ещё более сложную) проблему одновременного доступа к персистентным объектам. Модуль [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle) может преобразовывать сложный объект в поток байтов и обратно в объект с той же внутренней структурой. Самое очевидное применение этих потоков байтов – запись в файл, но их также можно передавать по сети или хранить в базе данных. Модуль [`shelve`](https://python-all.ru/3.4/library/shelve.html#module-shelve) предоставляет простой интерфейс для сериализации (pickle и unpickle) объектов в файлах баз данных стиля DBM.6162## 12.1.3. Интерфейс модуля6364Для сериализации иерархии объектов достаточно вызвать функцию [`dumps()`](https://python-all.ru/3.4/library/pickle.html#pickle.dumps). Аналогично, для десериализации потока данных вызывается функция [`loads()`](https://python-all.ru/3.4/library/pickle.html#pickle.loads). Однако если требуется более тонкий контроль над сериализацией и десериализацией, можно создать соответственно объект [`Pickler`](https://python-all.ru/3.4/library/pickle.html#pickle.Pickler) или [`Unpickler`](https://python-all.ru/3.4/library/pickle.html#pickle.Unpickler).6566Модуль [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle) предоставляет следующие константы:6768#### `pickle.HIGHEST_PROTOCOL`6970Целое число, наибольшая доступная [*версия протокола*](https://python-all.ru/3.4/library/pickle.html#pickle-protocols). Это значение может быть передано в качестве аргумента *протокол* функциям [`dump()`](https://python-all.ru/3.4/library/pickle.html#pickle.dump) и [`dumps()`](https://python-all.ru/3.4/library/pickle.html#pickle.dumps), а также конструктору [`Pickler`](https://python-all.ru/3.4/library/pickle.html#pickle.Pickler).7172#### `pickle.DEFAULT_PROTOCOL`7374Целое число, версия протокола по умолчанию [*протокола*](https://python-all.ru/3.4/library/pickle.html#pickle-protocols), используемая для pickling. Может быть меньше [`HIGHEST_PROTOCOL`](https://python-all.ru/3.4/library/pickle.html#pickle.HIGHEST_PROTOCOL). В настоящее время протоколом по умолчанию является 3 – новый протокол, разработанный для Python 3.7576Модуль [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle) предоставляет следующие функции для упрощения процесса упаковки (pickling):7778#### `pickle.dump(obj, file, protocol=None, *, fix_imports=True)`7980Записывает упакованное (pickled) представление объекта *obj* в открытый [*файловый объект*](https://python-all.ru/3.4/glossary.html#term-file-object) *file*. Это эквивалентно вызову `Pickler(file, protocol).dump(obj)`.8182Необязательный аргумент *протокол* (целое число) указывает упаковщику (pickler) использовать заданный протокол; поддерживаются протоколы от 0 до [`HIGHEST_PROTOCOL`](https://python-all.ru/3.4/library/pickle.html#pickle.HIGHEST_PROTOCOL). Если не указан, по умолчанию используется [`DEFAULT_PROTOCOL`](https://python-all.ru/3.4/library/pickle.html#pickle.DEFAULT_PROTOCOL). Если указано отрицательное число, выбирается [`HIGHEST_PROTOCOL`](https://python-all.ru/3.4/library/pickle.html#pickle.HIGHEST_PROTOCOL).8384Аргумент *file* должен иметь метод write(), принимающий один аргумент типа bytes. Таким образом, это может быть файл на диске, открытый для двоичной записи, экземпляр [`io.BytesIO`](https://python-all.ru/3.4/library/io.html#io.BytesIO) или любой другой пользовательский объект, соответствующий этому интерфейсу.8586Если *fix\_imports* равен true и *протокол* меньше 3, pickle попытается сопоставить новые имена Python 3 со старыми именами модулей, используемыми в Python 2, чтобы поток данных pickle был читаем в Python 2.8788#### `pickle.dumps(obj, protocol=None, *, fix_imports=True)`8990Возвращает упакованное (pickled) представление объекта в виде объекта [`bytes`](https://python-all.ru/3.4/library/functions.html#bytes), вместо записи в файл.9192Аргументы *protocol* и *fix\_imports* имеют тот же смысл, что и в [`dump()`](https://python-all.ru/3.4/library/pickle.html#pickle.dump).9394#### `pickle.load(file, *, fix_imports=True, encoding="ASCII", errors="strict")`9596Читает упакованное представление объекта из открытого [*файлового объекта*](https://python-all.ru/3.4/glossary.html#term-file-object) *file* и возвращает восстановленную иерархию объекта, заданную в нём. Это эквивалентно `Unpickler(file).load()`.9798Версия протокола pickle определяется автоматически, поэтому аргумент протокол не требуется. Байты, следующие за представлением объекта в pickle, игнорируются.99100Аргумент *file* должен иметь два метода: read() с целочисленным аргументом и readline() без аргументов. Оба метода должны возвращать bytes. Таким образом, *file* может быть файлом на диске, открытым для бинарного чтения, объектом [`io.BytesIO`](https://python-all.ru/3.4/library/io.html#io.BytesIO) или любым другим пользовательским объектом, удовлетворяющим этому интерфейсу.101102Необязательными ключевыми аргументами являются *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.103104#### `pickle.loads(bytes_object, *, fix_imports=True, encoding="ASCII", errors="strict")`105106Читает упакованную иерархию объекта из объекта [`bytes`](https://python-all.ru/3.4/library/functions.html#bytes) и возвращает восстановленную иерархию объекта, заданную в нём.107108Версия протокола pickle определяется автоматически, поэтому аргумент протокол не требуется. Байты, следующие за представлением объекта в pickle, игнорируются.109110Необязательными ключевыми аргументами являются *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.111112Модуль [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle) определяет три исключения:113114#### `exception pickle.PickleError`115116Общий базовый класс для других исключений при упаковке. Наследует [`Exception`](https://python-all.ru/3.4/library/exceptions.html#Exception).117118#### `exception pickle.PicklingError`119120Исключение, возникающее при обнаружении [`Pickler`](https://python-all.ru/3.4/library/pickle.html#pickle.Pickler) объекта, который невозможно упаковать. Наследует [`PickleError`](https://python-all.ru/3.4/library/pickle.html#pickle.PickleError).121122Обратитесь к разделу [*Какие объекты можно упаковывать и распаковывать?*](https://python-all.ru/3.4/library/pickle.html#pickle-picklable), чтобы узнать, какие объекты можно упаковывать.123124#### `exception pickle.UnpicklingError`125126Исключение, возникающее при проблемах с распаковкой объекта, таких как повреждение данных или нарушение безопасности. Наследует [`PickleError`](https://python-all.ru/3.4/library/pickle.html#pickle.PickleError).127128Обратите внимание, что во время распаковки могут возбуждаться и другие исключения, включая (но не ограничиваясь) AttributeError, EOFError, ImportError и IndexError.129130Модуль [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle) экспортирует два класса: [`Pickler`](https://python-all.ru/3.4/library/pickle.html#pickle.Pickler) и [`Unpickler`](https://python-all.ru/3.4/library/pickle.html#pickle.Unpickler).131132#### `class pickle.Pickler(file, protocol=None, *, fix_imports=True)`133134Он принимает двоичный файл для записи потока данных pickle.135136Необязательный целочисленный аргумент *protocol* указывает упаковщику, какой протокол использовать; поддерживаются протоколы с 0 по [`HIGHEST_PROTOCOL`](https://python-all.ru/3.4/library/pickle.html#pickle.HIGHEST_PROTOCOL). Если не указан, по умолчанию используется [`DEFAULT_PROTOCOL`](https://python-all.ru/3.4/library/pickle.html#pickle.DEFAULT_PROTOCOL). Если указано отрицательное число, выбирается [`HIGHEST_PROTOCOL`](https://python-all.ru/3.4/library/pickle.html#pickle.HIGHEST_PROTOCOL).137138Аргумент *file* должен иметь метод write(), принимающий один аргумент типа bytes. Таким образом, это может быть файл на диске, открытый для бинарной записи, экземпляр [`io.BytesIO`](https://python-all.ru/3.4/library/io.html#io.BytesIO) или любой другой пользовательский объект, удовлетворяющий этому интерфейсу.139140Если *fix\_imports* равен true и *протокол* меньше 3, pickle попытается сопоставить новые имена Python 3 со старыми именами модулей, используемыми в Python 2, чтобы поток данных pickle был читаем в Python 2.141142#### `dump(obj)`143144Записывает представление *obj* в виде pickle в открытый объект файла, переданный в конструкторе.145146#### `persistent_id(obj)`147148По умолчанию ничего не делает. Этот метод существует, чтобы подкласс мог его переопределить.149150Если [`persistent_id()`](https://python-all.ru/3.4/library/pickle.html#pickle.Pickler.persistent_id) возвращает `None`, *obj* упаковывается обычным образом. Любое другое значение заставляет [`Pickler`](https://python-all.ru/3.4/library/pickle.html#pickle.Pickler) выдать это значение как постоянный идентификатор для *obj*. Смысл этого постоянного идентификатора должен быть определён [`Unpickler.persistent_load()`](https://python-all.ru/3.4/library/pickle.html#pickle.Unpickler.persistent_load). Обратите внимание, что значение, возвращаемое [`persistent_id()`](https://python-all.ru/3.4/library/pickle.html#pickle.Pickler.persistent_id), само не может иметь постоянный идентификатор.151152См. [*Постоянство внешних объектов*](https://python-all.ru/3.4/library/pickle.html#pickle-persistent) для подробностей и примеров использования.153154#### `dispatch_table`155156Таблица диспетчеризации объекта-упаковщика – это реестр *функций приведения*, которые можно объявить с помощью [`copyreg.pickle()`](https://python-all.ru/3.4/library/copyreg.html#copyreg.pickle). Это отображение, ключами которого являются классы, а значениями – функции приведения. Функция приведения принимает один аргумент соответствующего класса и должна соответствовать тому же интерфейсу, что и метод [`__reduce__()`](https://python-all.ru/3.4/library/pickle.html#object.__reduce__).157158По умолчанию объект-упаковщик не имеет атрибута [`dispatch_table`](https://python-all.ru/3.4/library/pickle.html#pickle.Pickler.dispatch_table) и вместо этого использует глобальную таблицу диспетчеризации, управляемую модулем [`copyreg`](https://python-all.ru/3.4/library/copyreg.html#module-copyreg). Однако, чтобы настроить упаковку для конкретного упаковщика, можно установить атрибут [`dispatch_table`](https://python-all.ru/3.4/library/pickle.html#pickle.Pickler.dispatch_table) в объект, подобный словарю. В качестве альтернативы, если подкласс [`Pickler`](https://python-all.ru/3.4/library/pickle.html#pickle.Pickler) имеет атрибут [`dispatch_table`](https://python-all.ru/3.4/library/pickle.html#pickle.Pickler.dispatch_table), то он будет использоваться как таблица диспетчеризации по умолчанию для экземпляров этого класса.159160См. [*Таблицы диспетчеризации*](https://python-all.ru/3.4/library/pickle.html#pickle-dispatch) в качестве примеров использования.161162Новое в версии 3.3.163164#### `fast`165166Устарело. При установке в истинное значение включает быстрый режим. Быстрый режим отключает использование memo, тем самым ускоряя процесс упаковки за счёт отсутствия лишних кодов операций PUT. Его не следует использовать с самореферентными объектами, иначе [`Pickler`](https://python-all.ru/3.4/library/pickle.html#pickle.Pickler) будет рекурсировать бесконечно.167168Используйте [`pickletools.optimize()`](https://python-all.ru/3.4/library/pickletools.html#pickletools.optimize), если нужны более компактные упаковки.169170#### `class pickle.Unpickler(file, *, fix_imports=True, encoding="ASCII", errors="strict")`171172Принимает бинарный файл для чтения потока данных pickle.173174Версия протокола pickle определяется автоматически, поэтому аргумент протокола не нужен.175176Аргумент *file* должен иметь два метода: read() с целочисленным аргументом и readline() без аргументов. Оба метода должны возвращать bytes. Таким образом, *file* может быть файловым объектом на диске, открытым для бинарного чтения, объектом [`io.BytesIO`](https://python-all.ru/3.4/library/io.html#io.BytesIO) или любым другим пользовательским объектом, удовлетворяющим этому интерфейсу.177178Необязательные ключевые аргументы: *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-объекты.179180#### `load()`181182Читает представление объекта в pickle из открытого объекта файла, переданного в конструкторе, и возвращает восстановленную иерархию объектов, указанную в нём. Байты, следующие за представлением объекта в pickle, игнорируются.183184#### `persistent_load(pid)`185186По умолчанию вызывает [`UnpicklingError`](https://python-all.ru/3.4/library/pickle.html#pickle.UnpicklingError).187188Если определён, [`persistent_load()`](https://python-all.ru/3.4/library/pickle.html#pickle.Unpickler.persistent_load) должен вернуть объект, заданный постоянным идентификатором *pid*. При обнаружении недопустимого постоянного идентификатора должно быть вызвано [`UnpicklingError`](https://python-all.ru/3.4/library/pickle.html#pickle.UnpicklingError).189190См. [*Постоянство внешних объектов*](https://python-all.ru/3.4/library/pickle.html#pickle-persistent) для подробностей и примеров использования.191192#### `find_class(module, name)`193194Импортирует модуль *module* при необходимости и возвращает из него объект с именем *name*. Аргументы *module* и *name* – строки (тип [`str`](https://python-all.ru/3.4/library/stdtypes.html#str)). Обратите внимание: вопреки своему названию, [`find_class()`](https://python-all.ru/3.4/library/pickle.html#pickle.Unpickler.find_class) также используется для поиска функций.195196Подклассы могут переопределить этот метод для получения контроля над тем, объекты какого типа и каким образом могут быть загружены, что потенциально снижает риски безопасности. См. [*Ограничение глобальных объектов*](https://python-all.ru/3.4/library/pickle.html#pickle-restrict) для подробностей.197198## 12.1.4. Какие объекты можно сериализовать и десериализовать?199200Следующие типы можно сериализовать:201202- `None`, `True` и `False`203- целые числа, числа с плавающей запятой, комплексные числа204- строки, байты, байтовые массивы205- кортежи, списки, множества и словари, содержащие только сериализуемые объекты206- функции, определённые на верхнем уровне модуля (с помощью [`def`](https://python-all.ru/3.4/reference/compound_stmts.html#def), а не [`lambda`](https://python-all.ru/3.4/reference/expressions.html#lambda))207- встроенные функции, определённые на верхнем уровне модуля208- классы, определённые на верхнем уровне модуля209- экземпляры таких классов, у которых [`__dict__`](https://python-all.ru/3.4/library/stdtypes.html#object.__dict__) или результат вызова [`__getstate__()`](https://python-all.ru/3.4/library/pickle.html#object.__getstate__) поддаётся пиклингу (см. раздел [*Пиклинг экземпляров классов*](https://python-all.ru/3.4/library/pickle.html#pickle-inst) для подробностей).210211Попытка запакетить (pickle) непиклируемый объект вызовет исключение [`PicklingError`](https://python-all.ru/3.4/library/pickle.html#pickle.PicklingError); при этом в базовый файл может быть уже записано некоторое количество байт. Попытка запакетить сильно рекурсивную структуру данных может превысить максимальную глубину рекурсии – в этом случае будет возбуждено [`RuntimeError`](https://python-all.ru/3.4/library/exceptions.html#RuntimeError). Можно аккуратно увеличить этот предел с помощью [`sys.setrecursionlimit()`](https://python-all.ru/3.4/library/sys.html#sys.setrecursionlimit).212213Обратите внимание, что функции (встроенные и определённые пользователем) сериализуются по «полному» имени, а не по значению. [\[2\]](https://python-all.ru/3.4/library/pickle.html#id7) Это означает, что сериализуется только имя функции вместе с именем модуля, в котором она определена. Ни код функции, ни её атрибуты не сериализуются. Таким образом, определяющий модуль должен быть импортируем в среде десериализации, и модуль должен содержать именованный объект, иначе будет возбуждено исключение. [\[3\]](https://python-all.ru/3.4/library/pickle.html#id8)214215Аналогично, классы пиклятся по именованной ссылке, поэтому в среде распикливания действуют те же ограничения. Обратите внимание, что ни код класса, ни его данные не пиклятся, так что в следующем примере атрибут класса `attr` не восстанавливается в среде распикливания:216217```python218class Foo:219    attr = 'A class attribute'220221picklestring = pickle.dumps(Foo)222```223224Эти ограничения объясняют, почему сериализуемые функции и классы должны быть определены на верхнем уровне модуля.225226Аналогично, при пиклинге экземпляров классов код и данные самого класса не пиклятся вместе с ними. Пиклятся только данные экземпляра. Это сделано намеренно: можно исправлять ошибки в классе или добавлять методы и при этом загружать объекты, созданные более ранней версией класса. Если предполагается использовать долгоживущие объекты, которые переживут много версий класса, стоит поместить номер версии в объекты, чтобы метод [`__setstate__()`](https://python-all.ru/3.4/library/pickle.html#object.__setstate__) класса мог выполнить подходящие преобразования.227228## 12.1.5. Сериализация экземпляров классов229230В этом разделе описываются общие механизмы, позволяющие определять, настраивать и контролировать процесс сериализации и десериализации экземпляров классов.231232В большинстве случаев для того, чтобы экземпляры можно было пиклить, дополнительный код не требуется. По умолчанию pickle извлекает класс и атрибуты экземпляра через интроспекцию. При распикливании экземпляра класса его метод [`__init__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__init__) обычно *не* вызывается. Стандартное поведение сначала создаёт неинициализированный экземпляр, а затем восстанавливает сохранённые атрибуты. Следующий код показывает реализацию этого поведения:233234```python235def save(obj):236    return (obj.__class__, obj.__dict__)237238def load(cls, attributes):239    obj = cls.__new__(cls)240    obj.__dict__.update(attributes)241    return obj242```243244Классы могут изменить поведение по умолчанию, предоставив один или несколько специальных методов:245246#### `object.__getnewargs_ex__()`247248В протоколах 4 и новее классы, реализующие метод [`__getnewargs_ex__()`](https://python-all.ru/3.4/library/pickle.html#object.__getnewargs_ex__), могут определять значения, передаваемые методу [`__new__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__new__) при распикливании. Метод должен вернуть пару `(args, kwargs)`, где *args* – кортеж позиционных аргументов, а *kwargs* – словарь именованных аргументов для конструирования объекта. Они будут переданы методу [`__new__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__new__) при распикливании.249250Этот метод следует реализовать, если метод [`__new__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__new__) вашего класса требует аргументы только по ключу. В противном случае для совместимости рекомендуется реализовать [`__getnewargs__()`](https://python-all.ru/3.4/library/pickle.html#object.__getnewargs__).251252#### `object.__getnewargs__()`253254Этот метод служит той же цели, что и [`__getnewargs_ex__()`](https://python-all.ru/3.4/library/pickle.html#object.__getnewargs_ex__), но для протоколов 2 и новее. Он должен вернуть кортеж аргументов `args`, которые будут переданы методу [`__new__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__new__) при распикливании.255256В протоколах 4 и новее [`__getnewargs__()`](https://python-all.ru/3.4/library/pickle.html#object.__getnewargs__) не будет вызываться, если определён [`__getnewargs_ex__()`](https://python-all.ru/3.4/library/pickle.html#object.__getnewargs_ex__).257258#### `object.__getstate__()`259260Классы могут дополнительно влиять на то, как пиклятся их экземпляры. Если класс определяет метод [`__getstate__()`](https://python-all.ru/3.4/library/pickle.html#object.__getstate__), он вызывается, и возвращённый объект пиклится как содержимое экземпляра вместо содержимого словаря экземпляра. Если метод [`__getstate__()`](https://python-all.ru/3.4/library/pickle.html#object.__getstate__) отсутствует, то [`__dict__`](https://python-all.ru/3.4/library/stdtypes.html#object.__dict__) экземпляра пиклится как обычно.261262#### `object.__setstate__(state)`263264При распикливании, если класс определяет [`__setstate__()`](https://python-all.ru/3.4/library/pickle.html#object.__setstate__), он вызывается с распикленным состоянием. В этом случае объект состояния не обязан быть словарём. В противном случае распикленное состояние должно быть словарём, и его элементы присваиваются словарю нового экземпляра.265266> **Примечание**267>268> Если [`__getstate__()`](https://python-all.ru/3.4/library/pickle.html#object.__getstate__) возвращает ложное значение, метод [`__setstate__()`](https://python-all.ru/3.4/library/pickle.html#object.__setstate__) не будет вызываться при распикливании.269270Обратитесь к разделу [*Обработка объектов с состоянием*](https://python-all.ru/3.4/library/pickle.html#pickle-state) за дополнительной информацией об использовании методов [`__getstate__()`](https://python-all.ru/3.4/library/pickle.html#object.__getstate__) и [`__setstate__()`](https://python-all.ru/3.4/library/pickle.html#object.__setstate__).271272> **Примечание**273>274> Во время распикливания для экземпляра могут вызываться некоторые методы, такие как [`__getattr__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__getattr__), [`__getattribute__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__getattribute__) или [`__setattr__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__setattr__). Если эти методы полагаются на некоторое внутреннее инвариантное условие, тип должен реализовать [`__getnewargs__()`](https://python-all.ru/3.4/library/pickle.html#object.__getnewargs__) или [`__getnewargs_ex__()`](https://python-all.ru/3.4/library/pickle.html#object.__getnewargs_ex__) для установления такого инварианта; в противном случае не будут вызваны ни [`__new__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__new__), ни [`__init__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__init__).275276Как мы увидим, pickle не использует описанные выше методы напрямую. На самом деле эти методы являются частью протокола копирования, который реализует специальный метод [`__reduce__()`](https://python-all.ru/3.4/library/pickle.html#object.__reduce__). Протокол копирования предоставляет единый интерфейс для получения данных, необходимых для пиклинга и копирования объектов.[\[4\]](https://python-all.ru/3.4/library/pickle.html#id9)277278Хотя это мощный инструмент, реализация [`__reduce__()`](https://python-all.ru/3.4/library/pickle.html#object.__reduce__) непосредственно в классах чревата ошибками. Поэтому разработчикам классов следует по возможности использовать высокоуровневый интерфейс (т.е. [`__getnewargs_ex__()`](https://python-all.ru/3.4/library/pickle.html#object.__getnewargs_ex__), [`__getstate__()`](https://python-all.ru/3.4/library/pickle.html#object.__getstate__) и [`__setstate__()`](https://python-all.ru/3.4/library/pickle.html#object.__setstate__)). Однако мы покажем случаи, когда использование [`__reduce__()`](https://python-all.ru/3.4/library/pickle.html#object.__reduce__) является единственным вариантом или приводит к более эффективному пиклингу, или и то и другое.279280#### `object.__reduce__()`281282Интерфейс в настоящее время определён следующим образом. Метод [`__reduce__()`](https://python-all.ru/3.4/library/pickle.html#object.__reduce__) не принимает аргументов и должен возвращать либо строку, либо, предпочтительно, кортеж (возвращаемый объект часто называют «reduce-значением»).283284Если возвращается строка, она должна интерпретироваться как имя глобальной переменной. Это должно быть локальное имя объекта относительно его модуля; модуль pickle ищет объект в пространстве имён модуля. Такое поведение обычно полезно для одиночек (singletons).285286Если возвращается кортеж, он должен содержать от двух до пяти элементов. Необязательные элементы можно опустить или указать `None` в качестве их значения. Семантика каждого элемента по порядку:287288- Вызываемый объект, который будет вызван для создания начальной версии объекта.289- Кортеж аргументов для вызываемого объекта. Если вызываемый объект не принимает ни одного аргумента, должен быть передан пустой кортеж.290- Необязательно: состояние объекта, которое будет передано методу [`__setstate__()`](https://python-all.ru/3.4/library/pickle.html#object.__setstate__) объекта, как описано ранее. Если у объекта нет такого метода, значение должно быть словарём, и оно будет добавлено в атрибут [`__dict__`](https://python-all.ru/3.4/library/stdtypes.html#object.__dict__) объекта.291- Необязательно: итератор (не последовательность), возвращающий последовательные элементы. Эти элементы будут добавлены к объекту с помощью `obj.append(item)` или, пакетно, с помощью `obj.extend(list_of_items)`. В основном это используется для подклассов списков, но может использоваться и другими классами, если у них есть методы `append()` и `extend()` с подходящей сигнатурой. (Используется ли `append()` или `extend()`, зависит от версии протокола pickle и количества добавляемых элементов, поэтому оба должны поддерживаться.)292- Необязательно: итератор (не последовательность), возвращающий последовательные пары «ключ-значение». Эти элементы будут сохранены в объекте с помощью `obj[key] = value`. В основном это используется для подклассов словарей, но может использоваться и другими классами, если они реализуют [`__setitem__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__setitem__).293294#### `object.__reduce_ex__(protocol)`295296В качестве альтернативы может быть определён метод [`__reduce_ex__()`](https://python-all.ru/3.4/library/pickle.html#object.__reduce_ex__). Единственное отличие в том, что этот метод должен принимать один целочисленный аргумент – версию протокола. Если он определён, pickle будет предпочитать его методу [`__reduce__()`](https://python-all.ru/3.4/library/pickle.html#object.__reduce__). Кроме того, [`__reduce__()`](https://python-all.ru/3.4/library/pickle.html#object.__reduce__) автоматически становится синонимом расширенной версии. Основное назначение этого метода – предоставление обратно совместимых reduce-значений для старых версий Python.297298### 12.1.5.1. Сохранение внешних объектов299300Для обеспечения сохранности объектов модуль [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle) поддерживает понятие ссылки на объект, находящийся за пределами потока данных pickle. Такие объекты ссылаются через постоянный идентификатор, который может быть либо строкой из буквенно-цифровых символов (для протокола 0) [\[5\]](https://python-all.ru/3.4/library/pickle.html#id10), либо произвольным объектом (для любого более нового протокола).301302Разрешение таких постоянных идентификаторов не определяется модулем [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle); он делегирует это разрешение определенным пользователем методам пиклера и анпиклера – [`persistent_id()`](https://python-all.ru/3.4/library/pickle.html#pickle.Pickler.persistent_id) и [`persistent_load()`](https://python-all.ru/3.4/library/pickle.html#pickle.Unpickler.persistent_load) соответственно.303304Чтобы упаковать объекты, имеющие внешний постоянный идентификатор, пиклер должен иметь пользовательский метод [`persistent_id()`](https://python-all.ru/3.4/library/pickle.html#pickle.Pickler.persistent_id), который принимает объект в качестве аргумента и возвращает либо `None`, либо постоянный идентификатор для этого объекта. Когда возвращается `None`, пиклер просто упаковывает объект как обычно. Когда возвращается строка постоянного идентификатора, пиклер упакует этот объект вместе с маркером, чтобы анпиклер распознал его как постоянный идентификатор.305306Чтобы распаковать внешние объекты, анпиклер должен иметь пользовательский метод [`persistent_load()`](https://python-all.ru/3.4/library/pickle.html#pickle.Unpickler.persistent_load), который принимает объект постоянного идентификатора и возвращает объект, на который он ссылается.307308Вот исчерпывающий пример, показывающий, как постоянный идентификатор может использоваться для упаковки внешних объектов по ссылке.309310```python311# Простой пример, показывающий, как с помощью persistent ID можно упаковать внешние объекты по ссылке.312# внешние объекты по ссылке.313314import pickle315import sqlite3316from collections import namedtuple317318# Простой класс, представляющий запись в нашей базе данных.319MemoRecord = namedtuple("MemoRecord", "key, task")320321class DBPickler(pickle.Pickler):322323    def persistent_id(self, obj):324        # Вместо упаковки MemoRecord как обычного экземпляра класса, мы выводим325        # постоянный идентификатор.326        if isinstance(obj, MemoRecord):327            # Здесь наш постоянный идентификатор – это просто кортеж, содержащий метку и ключ, который ссылается на определённую запись в базе данных.328            # ключ, который ссылается на определённую запись в базе данных.329            return ("MemoRecord", obj.key)330        else:331            # Этот метод вызывается при каждом обнаружении постоянного идентификатора.332            # требуется упаковать как обычно.333            return None334335class DBUnpickler(pickle.Unpickler):336337    def __init__(self, file, connection):338        super().__init__(file)339        self.connection = connection340341    def persistent_load(self, pid):342        # Извлеките запись из базы данных по ссылке и верните её.343        # Всегда возбуждает исключение, если невозможно вернуть правильный объект.344        cursor = self.connection.cursor()345        type_tag, key_id = pid346        if type_tag == "MemoRecord":347            # Извлеките указанную запись из базы данных и верните её.348            cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),))349            key, task = cursor.fetchone()350            return MemoRecord(key, task)351        else:352            # Инициализируйте и наполните базу данных.353            # Извлеките записи для упаковки.354            # по постоянному идентификатору.355            raise pickle.UnpicklingError("unsupported persistent object")356357def main():358    import io359    import pprint360361    # Обновите запись для надёжности.362    conn = sqlite3.connect(":memory:")363    cursor = conn.cursor()364    cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)")365    tasks = (366        'give food to fish',367        'prepare group meeting',368        'fight with a zebra',369        )370    for task in tasks:371        cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,))372373    # Извлеките записи, которые требуется упаковать.374    cursor.execute("SELECT * FROM memos")375    memos = [MemoRecord(key, task) for key, task in cursor]376    # Выводит и нумерует строки в текстовом файле.377    file = io.BytesIO()378    DBPickler(file).dump(memos)379380    print("Pickled records:")381    pprint.pprint(memos)382383    # Обновите запись, для верности.384    cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1")385386    # Удаляет не подлежащие упаковке записи.387    file.seek(0)388    memos = DBUnpickler(file, conn).load()389390    print("Unpickled records:")391    pprint.pprint(memos)392393if __name__ == '__main__':394    main()395```396397### 12.1.5.2. Диспетчерские таблицы398399Если требуется настроить упаковку некоторых классов, не затрагивая другой код, зависящий от упаковки, можно создать упаковщик с частной диспетчерской таблицей.400401Глобальная диспетчерская таблица, управляемая модулем [`copyreg`](https://python-all.ru/3.4/library/copyreg.html#module-copyreg), доступна как `copyreg.dispatch_table`. Следовательно, можно использовать изменённую копию `copyreg.dispatch_table` в качестве частной диспетчерской таблицы.402403Например404405```python406f = io.BytesIO()407p = pickle.Pickler(f)408p.dispatch_table = copyreg.dispatch_table.copy()409p.dispatch_table[SomeClass] = reduce_SomeClass410```411412создаёт экземпляр [`pickle.Pickler`](https://python-all.ru/3.4/library/pickle.html#pickle.Pickler) с частной диспетчерской таблицей, которая обрабатывает класс `SomeClass` особым образом. В качестве альтернативы код413414```python415class MyPickler(pickle.Pickler):416    dispatch_table = copyreg.dispatch_table.copy()417    dispatch_table[SomeClass] = reduce_SomeClass418f = io.BytesIO()419p = MyPickler(f)420```421422делает то же самое, но все экземпляры `MyPickler` по умолчанию будут использовать одну и ту же диспетчерскую таблицу. Эквивалентный код с использованием модуля [`copyreg`](https://python-all.ru/3.4/library/copyreg.html#module-copyreg):423424```python425copyreg.pickle(SomeClass, reduce_SomeClass)426f = io.BytesIO()427p = pickle.Pickler(f)428```429430### 12.1.5.3. Обработка объектов с состоянием431432Вот пример, показывающий, как изменить поведение упаковки для класса. Класс `TextReader` открывает текстовый файл и возвращает номер строки и её содержимое каждый раз при вызове его метода `readline()`. Если экземпляр `TextReader` упаковывается, сохраняются все атрибуты, *кроме* члена файлового объекта. Когда экземпляр распаковывается, файл открывается заново, и чтение продолжается с последней позиции. Для реализации такого поведения используются методы [`__setstate__()`](https://python-all.ru/3.4/library/pickle.html#object.__setstate__) и [`__getstate__()`](https://python-all.ru/3.4/library/pickle.html#object.__getstate__).433434```python435class TextReader:436    """Вывести и пронумеровать строки в текстовом файле."""437438    def __init__(self, filename):439        self.filename = filename440        self.file = open(filename)441        self.lineno = 0442443    def readline(self):444        self.lineno += 1445        line = self.file.readline()446        if not line:447            return None448        if line.endswith('\n'):449            line = line[:-1]450        return "%i: %s" % (self.lineno, line)451452    def __getstate__(self):453        # Восстанавливает состояние ранее открытого файла. Для этого необходимо открыть его заново и читать, пока не будет восстановлено количество строк.454        # Наконец, сохраняет файл.455        # метод, чтобы избежать изменения исходного состояния.456        state = self.__dict__.copy()457        # Для любого другого объекта используйте обычную редукцию.458        del state['file']459        return state460461    def __setstate__(self, state):462        # Восстановить атрибуты экземпляра (например, filename и lineno).463        self.__dict__.update(state)464        # Получить дескриптор исходного буферного объекта.465        # открыть его заново и читать, пока количество строк не восстановится.466        file = open(self.filename)467        for _ in range(self.lineno):468            file.readline()469        # Наконец, сохраните файл.470        self.file = file471```472473Пример использования может выглядеть так:474475```python476>>> reader = TextReader("hello.txt")477>>> reader.readline()478'1: Hello world!'479>>> reader.readline()480'2: I am line number two.'481>>> new_reader = pickle.loads(pickle.dumps(reader))482>>> new_reader.readline()483'3: Goodbye!'484```485486## 12.1.6. Ограничение глобальных объектов487488По умолчанию распаковщик импортирует любой класс или функцию, найденные в данных pickle. Для многих приложений такое поведение неприемлемо, поскольку оно позволяет распаковщику импортировать и вызывать произвольный код. Просто подумайте, что делает этот вручную созданный поток данных pickle при загрузке:489490```python491>>> import pickle492>>> pickle.loads(b"cos\nsystem\n(S'echo hello world'\ntR.")493hello world4940495```496497В этом примере анпиклер импортирует функцию [`os.system()`](https://python-all.ru/3.4/library/os.html#os.system), а затем применяет строковый аргумент «echo hello world». Хотя этот пример безобиден, нетрудно представить такой, который может повредить систему.498499По этой причине можно управлять тем, что распаковывается, настроив [`Unpickler.find_class()`](https://python-all.ru/3.4/library/pickle.html#pickle.Unpickler.find_class). Вопреки своему названию, [`Unpickler.find_class()`](https://python-all.ru/3.4/library/pickle.html#pickle.Unpickler.find_class) вызывается всякий раз, когда запрашивается глобальный объект (т. е. класс или функция). Таким образом, можно либо полностью запретить глобальные объекты, либо ограничить их безопасным подмножеством.500501Вот пример анпиклера, который разрешает загрузку только нескольких безопасных классов из модуля [`builtins`](https://python-all.ru/3.4/library/builtins.html#module-builtins):502503```python504import builtins505import io506import pickle507508safe_builtins = {509    'range',510    'complex',511    'set',512    'frozenset',513    'slice',514}515516class RestrictedUnpickler(pickle.Unpickler):517518    def find_class(self, module, name):519        # Разрешать только безопасные классы из builtins.520        if module == "builtins" and name in safe_builtins:521            return getattr(builtins, name)522        # Запрещать всё остальное.523        raise pickle.UnpicklingError("global '%s.%s' is forbidden" %524                                     (module, name))525526def restricted_loads(s):527    """Вспомогательная функция, аналогичная pickle.loads()."""528    return RestrictedUnpickler(io.BytesIO(s)).load()529```530531Пример использования нашего десериализатора, работающего как задумано:532533```python534>>> restricted_loads(pickle.dumps([1, 2, range(15)]))535[1, 2, range(0, 15)]536>>> restricted_loads(b"cos\nsystem\n(S'echo hello world'\ntR.")537Traceback (most recent call last):538  ...539pickle.UnpicklingError: global 'os.system' is forbidden540>>> restricted_loads(b'cbuiltins\neval\n'541...                  b'(S\'getattr(__import__("os"), "system")'542...                  b'("echo hello world")\'\ntR.')543Traceback (most recent call last):544  ...545pickle.UnpicklingError: global 'builtins.eval' is forbidden546```547548Как показывают наши примеры, нужно быть осторожным с тем, что разрешается распаковывать. Поэтому если безопасность вызывает беспокойство, возможно, стоит рассмотреть альтернативы, например API маршалинга в [`xmlrpc.client`](https://python-all.ru/3.4/library/xmlrpc.client.html#module-xmlrpc.client) или сторонние решения.549550## 12.1.7. Производительность551552Последние версии протокола pickle (начиная с протокола 2 и выше) содержат эффективные двоичные кодировки для нескольких распространённых возможностей и встроенных типов. Кроме того, модуль [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle) имеет прозрачный оптимизатор, написанный на C.553554## 12.1.8. Примеры555556Для простейшего кода используйте функции [`dump()`](https://python-all.ru/3.4/library/pickle.html#pickle.dump) и [`load()`](https://python-all.ru/3.4/library/pickle.html#pickle.load).557558```python559import pickle560561# Произвольный набор объектов, поддерживаемых pickle.562data = {563    'a': [1, 2.0, 3, 4+6j],564    'b': ("character string", b"byte string"),565    'c': set([None, True, False])566}567568with open('data.pickle', 'wb') as f:569    # Запаковать словарь 'data', используя самый высокий доступный протокол.570    pickle.dump(data, f, pickle.HIGHEST_PROTOCOL)571```572573Следующий пример читает полученные сериализованные данные.574575```python576import pickle577578with open('data.pickle', 'rb') as f:579    # Версия используемого протокола определяется автоматически, поэтому580    # указывать её не нужно.581    data = pickle.load(f)582```583584> **См. также**585>586> **Модуль [`copyreg`](https://python-all.ru/3.4/library/copyreg.html#module-copyreg)**587>588> Регистрация конструктора интерфейса pickle для расширенных типов.589>590> **Модуль [`pickletools`](https://python-all.ru/3.4/library/pickletools.html#module-pickletools)**591>592> Инструменты для работы и анализа сериализованных данных.593>594> **Модуль [`shelve`](https://python-all.ru/3.4/library/shelve.html#module-shelve)**595>596> Индексированные базы данных объектов; использует597>598> [`pickle`](https://python-all.ru/3.4/library/pickle.html#module-pickle)599>600> .601>602> **Модуль [`copy`](https://python-all.ru/3.4/library/copy.html#module-copy)**603>604> Поверхностное и глубокое копирование объектов.605>606> **Модуль [`marshal`](https://python-all.ru/3.4/library/marshal.html#module-marshal)**607>608> Высокопроизводительная сериализация встроенных типов.609610Сноски611612| [\[1\]](https://python-all.ru/3.4/library/pickle.html#id1) | Не путайте это с модулем [`marshal`](https://python-all.ru/3.4/library/marshal.html#module-marshal) |613| --- | --- |614615| [\[2\]](https://python-all.ru/3.4/library/pickle.html#id2) | Вот почему функции [`lambda`](https://python-all.ru/3.4/reference/expressions.html#lambda) не могут быть упакованы: все функции [`lambda`](https://python-all.ru/3.4/reference/expressions.html#lambda) имеют одно и то же имя: `<lambda>`. |616| --- | --- |617618| [\[3\]](https://python-all.ru/3.4/library/pickle.html#id3) | Возникающее исключение, скорее всего, будет [`ImportError`](https://python-all.ru/3.4/library/exceptions.html#ImportError) или [`AttributeError`](https://python-all.ru/3.4/library/exceptions.html#AttributeError), но может быть и другим. |619| --- | --- |620621| [\[4\]](https://python-all.ru/3.4/library/pickle.html#id4) | Модуль [`copy`](https://python-all.ru/3.4/library/copy.html#module-copy) использует этот протокол для операций поверхностного и глубокого копирования. |622| --- | --- |623624| [\[5\]](https://python-all.ru/3.4/library/pickle.html#id5) | Ограничение на алфавитно-цифровые символы связано с тем, что постоянные идентификаторы в протоколе 0 разделяются символом новой строки. Поэтому если в постоянных идентификаторах встречаются какие-либо символы новой строки, результирующий pickle станет нечитаемым. |625| --- | --- |626