pickle python это что
Как хранить объекты Python со сложной структурой
Leo Matyushkin
Время от времени требуется сохранить на диск или отослать по сети объект со сложной структурой. Например, текущее состояние нейронной сети, находящейся в процессе обучения. Процесс перевода структуры данных в цепочку битов называется сериализацией.
После прочтения статьи вы будете знать:
Сериализация в Python
Итак, сериализация (англ. serialization, marshalling) – это способ преобразования структуры данных в линейную форму, которую можно сохранить или передать по сети. Обратный процесс преобразования сериализованного объекта в исходную структуру данных называется десериализацией (англ. deserialization, unmarshalling).
В стандартной библиотеке Python три модуля позволяют сериализовать и десериализовать объекты:
Кроме того, Python поддерживает XML, который также можно применять для сериализации объектов.
Модуль json обеспечивает работу со стандартными файлами JSON. Это широко используемый формат обмена данными, удобный для чтения и не зависящий от языка программирования. С помощью модуля json вы можете сериализовать и десериализовать стандартные типы данных Python:
Внутри модуля pickle
Модуль pickle содержит четыре основные функции:
В коде ниже показано, как создаётся и сериализуется экземпляр класса. Затем мы изменяем значение внутреннего словаря. Для восстановления исходной структуры можно использовать сохранённый с помощью pickle объект.
Таким образом, pickle создаёт глубокую копию исходной структуры.
Форматы протоколов модуля pickle
Модуль pickle специфичен для Python — результаты сериализации могут быть прочитаны только другой программой на Python. Но даже если вы работаете только с Python, полезно знать, как модуль эволюционировал со временем. От версии протокола зависит совместимость. Сейчас существует 6 версий протоколов:
Сериализуемые и несериализуемые типы
Попытавшись запустить эту программу, мы получим исключение: pickle не может сериализовать лямбда-функцию:
Попробуем заменить pickle на dill (библиотеку можно установить с помощью pip):
Запустим код и увидим, что модуль dill сериализует лямбда-функцию без ошибок:
Ещё одна особенность dill заключается в том, что он умеет сериализовать сеанс интерпретатора:
В этом примере после запуска интерпретатора и ввода нескольких выражений мы импортируем модуль dill и вызываем dump_session() для сериализации сеанса в файле test.pkl в текущем каталоге:
Запустим новый экземпляр интерпретатора и загрузим файл test.pkl для восстановления последнего сеанса:
В подобных случаях нужно исключить несериализуемый объект из процесса сериализации и повторно инициализировать после десериализации.
В следующем примере показано, как можно определить класс с несколькими атрибутами и исключить один атрибут из сериализации с помощью __getstate__() :
Если мы запустим этот пример, а затем десериализуем объект, то увидим, что новый экземпляр не содержит атрибут c :
Мы также можем выполнить дополнительные инициализации в процессе десериализации. Например, добавить исключённый объект c обратно в десериализованную сущность. Для этого используется метод __setstate__() :
Сжатие сериализованных объектов
Формат данных pickle является компактным двоичным представлением структуры объекта, но мы всё равно можем её оптимизировать, используя сжатие. Для bzip2-сжатия сериализованной строки можно использовать модуль стандартной библиотеки bz2 :
Безопасность отправки данных в формате pickle
Процесс сериализации удобен, когда необходимо сохранить состояние объекта на диск или передать по сети. Однако это не всегда безопасно. Как мы обсудили выше, при десериализации объекта в методе __setstate__() может выполняться любой произвольный код. В том числе код злоумышленника.
Простое правило гласит: никогда не десериализуйте данные, поступившие из подозрительного источника или ненадёжной сети. Чтобы предотвратить атаку посредника, используйте модуль стандартной библиотеки hmac для создания подписей и их проверки.
Вы можете протестировать этот скрипт на Mac или Linux, открыв терминал и набрав команду nc для прослушивания порта 8080 :
Это будет терминал атакующего. Затем открываем терминал на том же компьютере (или другом компьютере той же сети) и выполняем приведённый код Python. IP-адрес в коде нужно заменить на IP-адрес атакующего терминала. Выполнив следующую команду, жертва предоставит атакующему доступ:
При запуске скрипта жертвой в терминале злоумышленника оболочка Bash перейдёт в активное состояние:
Эта консоль позволить атакующему работать непосредственно на вашей системе.
Заключение
Теперь вы знаете, как работать с модулями pickle и dill для преобразования иерархии объектов со сложной структурой в поток байтов. Структуры можно сохранять на диск или передавать в виде байтовой строки по сети. Вы также знаете, что процесс десериализации нужно использовать с осторожностью. Если у вас остались вопросы, задайте их в комментарии под постом.
Модуль Python pickle: как сохранить объекты в Python
Оглавление Сериализация в Python Внутри модуля pickle Форматы протокола модуля Python pickle Picklable и Unpicklable типы Сжатие Pickled объектов Проблемы…
В этом уроке вы узнаете:
Сериализация в Python
Процесс сериализации – это способ преобразования структуры данных в линейную форму, которая может храниться или передаваться по сети.
Сериализация может использоваться в самых разных ситуациях. Одним из наиболее распространенных применений является сохранение состояния нейронной сети после фазы обучения, чтобы вы могли использовать его позже без необходимости повторять обучение.
Python предлагает три различных модуля в стандартной библиотеке, которые позволяют сериализовать и десериализовывать объекты:
json Модуль является новейшим из трех. Позволяет работать со стандартными файлами JSON. JSON – это очень удобный и широко используемый формат для обмена данными.
Есть несколько причин выбрать формат JSON : он удобен для чтения и не зависит от языка и легче XML. С помощью json модуля вы можете сериализовать и десериализовать несколько стандартных типов Python:
Модуль Python pickle – это еще один способ сериализации и десериализации объектов в Python. Он отличается от json модуля тем, что сериализует объекты в двоичном формате, что означает, что результат не читается человеком. Тем не менее, он также быстрее и работает со многими другими типами Python, включая ваши пользовательские объекты.
Примечание: С этого момента, вы будете видеть термины pickling и unpickling используется для обозначения сериализации и десериализации с Python pickle модуля.
Итак, у вас есть несколько различных способов сериализации и десериализации объектов в Python. Но какой из них вы должны использовать? Короткий ответ: нет единого решения для всех. Все зависит от вашего варианта использования.
Вот три основных руководства для принятия решения, какой подход использовать:
Внутри pickle модуля Python
Модуль Python pickle основном состоит из четырех методов:
Первые два метода используются во время процесса pickling, а два других используются во время unpickling. Единственная разница между dump() и dumps() заключается в том, что первый создает файл, содержащий результат сериализации, а второй возвращает строку.
Рассмотрим следующий пример. Допустим, у вас есть пользовательский класс example_class с несколькими разными атрибутами, каждый из которых имеет свой тип:
В приведенном ниже примере показано, как создать экземпляр класса и выбрать экземпляр, чтобы получить простую строку. После выбора класса вы можете изменить значение его атрибутов, не затрагивая выбранную строку. Затем вы можете снять выделенную строку в другой переменной, восстановив точную копию ранее выбранного класса:
Наконец, вы открываете строку для совершенно нового экземпляра. То, что вы получаете, является глубокой копией вашей исходной структуры объекта с момента начала процесса pickling.
Форматы протокола pickle модуля
Как уже упоминалось выше, pickle модуль является специфичным для Python, и результат процесса pickling может быть прочитан только другой программой Python. Но даже если вы работаете с Python, важно знать, что pickle модуль эволюционировал со временем.
Это означает, что если вы выбрали объект с определенной версией Python, вы не сможете удалить его с более старой версией. Совместимость зависит от версии протокола, который вы использовали для процесса травления.
Примечание. Более новые версии протокола предлагают больше функций и улучшений, но ограничены более высокими версиями интерпретатора. Обязательно учитывайте это при выборе протокола для использования.
Чтобы определить самый высокий протокол, который поддерживает ваш интерпретатор, вы можете проверить значение pickle.HIGHEST_PROTOCOL атрибута.
Выбираемые и необратимые типы
Вы уже узнали, что pickle модуль Python может сериализовать гораздо больше типов, чем json модуль. Тем не менее, не все picklable. Список unpicklable объектов включает соединения с базой данных, открытые сетевые сокеты, запущенные потоки и др.
Чтобы проверить этот модуль, вы можете попробовать выбрать lambda функцию:
Если вы попытаетесь запустить эту программу, вы получите исключение, потому что pickle модуль Python не может сериализовать lambda функцию:
Теперь попробуйте заменить pickle модуль Python на, dill чтобы увидеть, есть ли разница:
Если вы запустите этот код, вы увидите, что dill модуль сериализует lambda без возврата ошибки:
Еще одна интересная особенность dill заключается в том, что он может даже сериализовать весь сеанс интерпретатора. Вот пример:>>>
В этом примере вы запускаете интерпретатор, импортируете модуль и определяете lambda функцию вместе с несколькими другими переменными. Затем вы импортируете dill модуль и вызываете dump_session() для сериализации всей сессии.
Если все идет хорошо, вы должны получить test.pkl файл в текущем каталоге:
Теперь вы можете запустить новый экземпляр интерпретатора и загрузить test.pkl файл для восстановления вашего последнего сеанса:>>>
Первое globals().items() утверждение показывает, что интерпретатор находится в исходном состоянии. Это означает, что вам нужно импортировать dill модуль и вызвать load_session() для восстановления сеанса сериализованного интерпретатора.
Итак, как вы можете решить эту проблему?
Решением в этом случае является исключение объекта из процесса сериализации и повторная инициализация соединения после десериализации объекта.
В следующем примере вы увидите, как вы можете определить класс с несколькими атрибутами и исключить один атрибут из сериализации с помощью __getstate()__ :
В этом примере вы создаете объект с тремя атрибутами. Поскольку один из атрибутов – это lambda объект, его нельзя unpicklable стандартным pickle модулем.
Если вы запустите этот пример и затем десериализуете объект, то увидите, что новый экземпляр не содержит c атрибут:
Но что, если вы захотите выполнить некоторые дополнительные инициализации при снятии травления, скажем, добавив исключенный c объект обратно в десериализованный экземпляр? Вы можете сделать это с помощью __setstate__() :
Сжатие Pickled объектов
В следующем примере вы возьмете строку, выделите ее, а затем сожмете ее с помощью bz2 библиотеки:>>>
При использовании сжатия помните, что файлы меньшего размера создаются за счет более медленного процесса.
Проблемы безопасности с pickle модулем Python
Теперь вы знаете, как использовать pickle модуль для сериализации и десериализации объектов в Python. Процесс сериализации очень удобен, когда вам нужно сохранить состояние вашего объекта на диск или передать его по сети.
Итак, что вы можете сделать, чтобы уменьшить этот риск?
В следующем примере показано, как открепление несанкционированного доступа может раскрыть вашу систему злоумышленникам, даже предоставив им работающую удаленную оболочку:
Вот как вы можете безопасно протестировать этот скрипт на вашем Mac или Linux. Сначала откройте терминал и используйте nc команду для прослушивания соединения с портом 8080:
Выполнив этот код, жертва предоставит атакующему оболочку:
Если все работает, на атакующей консоли появится оболочка Bash. Эта консоль теперь может работать непосредственно на атакуемой системе:
Итак, позвольте мне повторить эту критическую точку еще раз: не используйте pickle модуль для десериализации объектов из ненадежных источников!
Вывод
Теперь вы знаете, как использовать pickle модуль Python для преобразования иерархии объектов в поток байтов, который можно сохранить на диск или передать по сети. Вы также знаете, что процесс десериализации в Python должен использоваться с осторожностью, поскольку извлечение чего-либо из ненадежного источника может быть чрезвычайно опасным.
В этом уроке вы узнали:
Модуль Pickle в Python
Pickle в Python используется для сериализации и десериализации структуры объекта. Любой объект можно законсервировать, чтобы потом сохранить на диске.
Сначала pickle сериализует объект, а затем преобразует объект в символьный поток, чтобы он содержал всю информацию, необходимую для восстановления объекта в другом скрипте.
Обратите внимание, что модуль pickle не защищен от ошибочных или злонамеренно созданных данных в соответствии с документацией. Поэтому никогда не отбирайте данные, полученные из ненадежных или не аутентифицированных источников.
pickle.dump()
В этом разделе мы узнаем, как хранить данные с помощью Python pickle. Для этого мы должны сначала импортировать модуль pickle.
Затем используйте функцию pickle.dump() для сохранения данных объекта в файле. Функция pickle.dump() принимает 3 аргумента. Первый аргумент – это объект, который вы хотите сохранить. Второй аргумент – это объект файла, который вы получаете, открывая желаемый файл в двоичном режиме записи (wb). И третий аргумент – это аргумент «ключ-значение». Этот аргумент определяет протокол. Существует два типа протокола – pickle.HIGHEST_PROTOCOL и pickle.DEFAULT_PROTOCOL. Пример кода:
Следующая программа предложит вам ввести некоторые данные. В моем случае это было так.
pickle.load()
Чтобы получить данные, шаги довольно просты. Для этого вам нужно использовать функцию pickle.load(). Основным аргументом функции загрузки pickle является объект файла, который вы получаете, открывая файл в режиме двоичного чтения (rb).
Давайте напишем код для получения данных, которые мы обработали, используя код дампа pickle.
Результат будет следующим:
Пример
Я сделал короткое видео, показывающее выполнение примеров программы pickle – сначала для сохранения данных в файл, а затем для их загрузки и печати.
Как вы можете видеть, файл, созданный через pickle dump, является двоичным файлом и показывает символы мусора в текстовом редакторе.
Важные замечания
Несколько важных моментов о модуле pickle в python:
Модуль Pickle в Python
Pickling – популярный способ консервирования продуктов. Согласно Википедии, это тоже довольно древняя процедура – хотя происхождение маринования неизвестно, древние месопотамцы, вероятно, использовали этот процесс 4400 лет назад. Поместив продукт в определенный раствор, можно увеличить срок его хранения. Другими словами, это метод, который позволяет нам хранить пищу для последующего употребления.
Если вы разработчик Python, однажды вам может понадобиться способ хранения ваших объектов для последующего использования.
Что такое сериализация в Python?
Сериализация в Python – это процесс преобразования объектов или структур данных в байтовые потоки или строки. Поток байтов – это один байт состоит из 8 бит нулей и единиц. Эти байтовые потоки затем можно легко сохранить или передать. Это позволяет разработчикам сохранять, например, данные конфигурации или прогресс пользователя, а затем сохранять их (на диске или в базе данных) или отправлять в другое место.
Объекты в Python также можно сериализовать с помощью модуля под названием Pickle.
Одним из основных отличий маринования объектов в Python от маринования овощей является неизбежное и необратимое изменение вкуса и текстуры маринованной пищи. Между тем, маринованные объекты можно легко вернуть в их первоначальную форму. Кстати, этот процесс широко известен, как десериализация.
Pickling (или сериализацию в целом) не следует путать со сжатием. Целью Pickling является перевод данных в формат, который может быть перенесен из ОЗУ на диск. С другой стороны, сжатие – это процесс кодирования данных с использованием меньшего количества бит (для экономии места на диске).
Сериализация особенно полезна в любом программном обеспечении, где важно иметь возможность сохранить некоторый прогресс на диске, выйти из программы, а затем загрузить прогресс обратно после повторного открытия программы. Видеоигры могут быть наиболее интуитивным примером полезности сериализации, но есть много других программ, в которых сохранение и загрузка данных или прогресса пользователя имеет решающее значение.
Сравнение pickle и JSON
Возможно, вы слышали о JSON (нотация объектов JavaScript), который является популярным форматом, который также позволяет разработчикам сохранять и передавать объекты, закодированные в виде строк. Этот метод сериализации имеет некоторые преимущества перед сохранением. Формат JSON удобочитаем, не зависит от языка и быстрее, чем pickle.
Однако у него есть и некоторые важные ограничения. Что наиболее важно, по умолчанию только ограниченное подмножество встроенных типов Python может быть представлено JSON. С помощью Pickle мы можем легко сериализовать очень широкий спектр типов Python и, что важно, настраиваемые классы. Это означает, что нам не нужно создавать настраиваемую схему (как мы делаем для JSON) и писать сериализаторы и парсеры, подверженные ошибкам. С Pickle вся тяжелая работа будет сделана за вас.
Что можно сериализовать?
Важно помнить, что травление не является независимым от языка методом сериализации, поэтому ваши консервированные данные могут быть извлечены только с помощью Python. Более того, важно убедиться, что объекты обрабатываются с использованием той же версии Python, которая будет использоваться для их выделения. В этом случае смешивание версий может вызвать множество проблем.
Кроме того, функции выбираются по ссылкам на их имена, а не по их значениям. Полученный в результате Pickling не содержит информации о коде или атрибутах функции. Следовательно, вы должны убедиться, что среда, в которой функция не выбрана, может импортировать функцию. Другими словами, если мы выберем функцию, а затем удалим ее в среде, где она либо не определена, либо не импортирована, возникнет исключение.
Также очень важно отметить, что маринованные предметы могут использоваться специально. Например, извлечение данных из ненадежного источника может привести к выполнению вредоносного кода.
Использование модуля
В следующем очень простом примере показаны основы использования модуля Pickle в Python 3:
Во-первых, мы должны импортировать модуль pickle, что выполняется в строке 1. В строке 3 мы определяем простой список из трех элементов, который будет обработан.
В строке 5 мы указываем, что имя нашего выходного файла pickle будет test_pickle.pkl. Используя параметр wb, мы сообщаем программе, что хотим записать (w) двоичные данные (b) внутри нее (потому что мы хотим создать поток байтов). Обратите внимание, что расширение pkl не обязательно – мы используем его в этом руководстве, потому что это расширение включено в документацию Python.
В строке 6 мы используем метод pickle.dump(), чтобы собрать наш тестовый список и сохранить его в файле test_pickle.pkl.
Я рекомендую вам попробовать открыть сгенерированный файл pickle в текстовом редакторе. Вы быстро заметите, что поток байтов определенно не является удобочитаемым форматом.
Распаковка
Теперь давайте раскроем содержимое тестового файла pickle и вернем наш объект к его исходной форме.
Как видите, эта процедура не сложнее, чем когда мы мариновали объект. В строке 3 мы снова открываем наш файл test_pickle.pkl, но на этот раз наша цель – прочитать (r) двоичные данные (b), хранящиеся в нем.
Затем, в строке 5, мы используем метод pickle.load(), чтобы распаковать наш список и сохранить его в переменной unpickled_list.
Затем вы можете распечатать содержимое списка, чтобы убедиться, что он идентичен списку, который мы выбрали в предыдущем примере. Вот результат выполнения приведенного выше кода:
Сериализация и распаковка нестандартных объектов
Как я упоминал ранее, используя Pickle, вы можете сериализовать свои собственные настраиваемые объекты. Взгляните на следующий пример:
Как видите, этот пример почти такой же простой, как и предыдущий. Между строками 3 и 7 мы определяем простой класс, который содержит один атрибут и один метод, который изменяет этот атрибут. В строке 9 мы создаем экземпляр этого класса и сохраняем его в переменной cucumber, а в строке 10 мы устанавливаем цвет его атрибута на «зеленый».
Затем, используя те же функции, что и в предыдущем примере, мы сериализуем и отделяем наш только что созданный объект. Выполнение приведенного выше кода приводит к следующему выводу:
Помните, что мы можем распаковать объект только в среде, где класс Veggy либо определен, либо импортирован. Если мы создадим новый скрипт и попытаемся выделить объект без импорта класса Veggy, мы получим «AttributeError». Например, выполните следующий скрипт:
В выводе приведенного выше скрипта вы увидите следующую ошибку:
Заключение
Как видите, благодаря модулю Pickle сериализация объектов Python довольно проста. В наших примерах мы выбрали простой список, но вы можете использовать тот же метод для сохранения большого спектра типов данных Python, если вы убедитесь, что ваши объекты содержат только другие выбираемые объекты.
У Pickling есть некоторые недостатки, самый большой из которых может заключаться в том, что вы можете распаковать свои данные только с помощью Python – если вам нужно кросс-языковое решение, JSON определенно лучший вариант. И, наконец, помните, что сериализованные объекты можно использовать для переноса кода, который вы не обязательно хотите выполнять.
pickle — Сериализация объектов Python¶
Исходный код: Lib/pickle.py
Модуль pickle не безопасен. Unpickle только те данные, которым вы доверяете.
Существует возможность создания вредоносных pickle данных, которые будут выполнить произвольный код во время анпиклинга. Никогда не отцепляйте данные, которые могли быть получены из ненадежного источника, или которые могли быть подделаны.
Связь с другими модулями Python¶
Сравнение с marshal ¶
Модуль pickle отличается от marshal несколькими значимыми способами:
Модуль pickle отслеживает уже сериализованные объекты, поэтому последующие ссылки на тот же объект больше не будут сериализованы. marshal этого не делает.
marshal не может быть используемый, чтобы преобразовать в последовательную форму определенные пользователями классы и их сущности. pickle может сохранять и восстанавливать класс сущности прозрачно, однако определение класса должно быть импортируемым и существовать в том же модуле, что и при сохранении объекта.
Сравнение с json ¶
Существуют принципиальные различия между протоколами pickle и JSON (JavaScript Object Notation):
Модуль json : стандартный библиотечный модуль, позволяющий выполнять сериализацию и десериализацию JSON.
Формат потока данных¶
Формат данных используемый по pickle является Python-specific. Это имеет то преимущество, что не существует ограничений, налагаемых внешними стандартами, такими как JSON или XDR (которые не могут представлять совместное использование указателей); однако это означает, что программы не-Python могут быть не в состоянии реконструировать объекты pickled Python.
По умолчанию формат pickle данных использует относительно компактное двоичное представление. Если вам нужны оптимальные особенности размера, вы можете эффективно данные о compress pickled.
Есть в настоящее время 6 различных протоколов, которые могут быть используемый для пиклинг. Чем выше протокол используемый, тем более поздняя версия Python необходима для чтения произведенных pickle.
Сериализация является более примитивным понятием, чем упорство; несмотря на то, что pickle считывает и записывает объекты файла, он не обрабатывает ни проблему именования постоянных объектов, ни (еще более сложную) проблему одновременного доступа к постоянным объектам. Модуль pickle может преобразовывать сложный объект в поток байтов и может преобразовывать поток байтов в объект с той же внутренней структурой. Возможно, самое очевидное, что нужно сделать с этими байтовыми потоками, это записать их в файл, но также возможно отправить их по сети или сохранить в базе данных. Модуль shelve обеспечивает простой интерфейс для pickle и открепления объектов в файлах базы данных в стиле DBM.
Интерфейс модуля¶
Модуль pickle предоставляет следующие константы:
Изменено в версии 3.0: По умолчанию используется протокол 3.
Изменено в версии 3.8: По умолчанию используется протокол 4.
Модуль pickle предоставляет следующие функции, чтобы сделать процесс пиклинг более удобным:
pickle. dump ( obj, file, protocol=None, *, fix_imports=True, buffer_callback=None ) ¶
Изменено в версии 3.8: Добавлен аргумент buffer_callback.
Возвращает представление pickled объекта obj как bytes возражают, вместо того, чтобы писать это файлу.
Изменено в версии 3.8: Добавлен аргумент buffer_callback.
Версия протокола pickle обнаруживается автоматически, поэтому аргумент протокола не требуется. Байты за pickled представлением объекта игнорируются.
Изменено в версии 3.8: Добавлен аргумент buffers.
Версия протокола pickle обнаруживается автоматически, поэтому аргумент протокола не требуется. Байты за pickled представлением объекта игнорируются.
Изменено в версии 3.8: Добавлен аргумент buffers.
Модуль pickle определяет три исключения:
exception pickle. PickleError ¶
exception pickle. PicklingError ¶
exception pickle. UnpicklingError ¶
Обратите внимание, что другие исключения могут также быть подняты во время анпиклинга, включая (но не обязательно ограничены), AttributeError, EOFError, ImportError и IndexError.
class pickle. Pickler ( file, protocol=None, *, fix_imports=True, buffer_callback=None ) ¶
Для записи потока pickle данных требуется двоичный файл.
Аргумент file должен иметь метод write (), который принимает один аргумент в байтах. Таким образом, это может быть файл на диске, открытый для двоичной записи, io.BytesIO сущность или любой другой пользовательский объект, соответствующий этому интерфейсу.
Если fix_imports имеет значение true и protocol меньше 3, pickle попытается сопоставить новые имена Python 3 со старыми именами модулей используемый в Python 2, чтобы поток pickle данных можно было прочитать с помощью Python 2.
Если buffer_callback имеет значение None (по умолчанию), представления буфера сериализуются в file как часть потока pickle.
Это ошибка, если buffer_callback не None и protocol None или меньше 5.
Изменено в версии 3.8: Добавлен аргумент buffer_callback.
Напишите представление pickled obj к открытому объекту файла, данному в конструкторе.
По умолчанию ничего не делать. Это существует, чтобы подкласс мог переопределить его.
Добавлено в версии 3.3.
Добавлено в версии 3.8.
Запрещен. Включить быстрый режим, если установлено в истинный значение. Быстрый режим отключает использование записки, поэтому ускорение процесса пиклинг, не производя лишний PUT опкоды. Это не должен быть используемый с самосправочными объектами, делание иначе заставит Pickler повторно проклинать бесконечно.
class pickle. Unpickler ( file, *, fix_imports=True, encoding=»ASCII», errors=»strict», buffers=None ) ¶
Для чтения потока pickle данных требуется двоичный файл.
Версия протокола pickle обнаруживается автоматически, поэтому аргумент протокола не требуется.
Аргумент file должен иметь три метода: метод read(), который принимает целочисленный аргумент, метод readinto(), который принимает аргумент буфера, и метод readline(), который не требует аргументов, как в io.BufferedIOBase интерфейс. Таким образом, file может быть файлом на диске, открытым для двоичного чтения, объектом io.BytesIO или любым другим настраиваемым объектом, который соответствует этому интерфейсу.
Если buffers имеет значение None (по умолчанию), то все данные, необходимые для десериализации, должны содержаться в потоке pickle. Это означает, что аргумент buffer_callback был None при создании экземпляра Pickler (или при вызове dump() или dumps() ).
Изменено в версии 3.8: Добавлен аргумент buffers.
Прочитайте представление pickled объекта от открытого объекта файла, данного в конструкторе и возвращает воссозданная иерархия объекта, определенная там. Байты за pickled представлением объекта игнорируются.
Если определено, persistent_load() должен возвращает объект, указанный постоянным идентификатором pid. Если с недействительным настойчивым ID сталкиваются, UnpicklingError должен быть поднят.
Импортировать module при необходимости и возвращает вызванный name из него объект, где аргументы module и name являются str объектами. Обратите внимание, в отличие от его названия предполагает, что find_class() также является используемый для поиска функций.
class pickle. PickleBuffer ( buffer ) ¶
Оболочка для буфера, представляющая выбираемые данные. buffer должен быть buffer-providing объектом, таким как байтоподобный объект или N-мерный массив.
Добавлено в версии 3.8.
Возвращает memoryview области памяти, лежащей в основе этого буфера. Объект возвращенный представляет собой одномерное C-непрерывное запоминающее представление с форматом B (байты без знака). BufferError поднимается, если буфер не является ни C, ни Fortran-смежным.
Освободить базовый буфер, предоставленный объектом PickleBuffer.
Что может быть pickled и unpickled?¶
Следующие типы могут быть pickled:
Обратите внимание, что функции (встроенный и определенный пользователями) являются pickled «полностью компетентной» ссылкой имени, не значение. [2] это означает, что pickled является только имя функции, а также имя модуля, в котором определена функция. Ни код функции, ни какая-либо ее функция атрибуты не являются pickled. Таким образом, определяющий модуль должен быть импортирован в среде отмены выбора, а модуль должен содержать именованный объект, в противном случае возникает исключение. [3]
Эти ограничения являются причиной того, что выбираемые функции и классы должны быть определены на верхнем уровне модуля.
Пиклинг класса сущности¶
Классы могут изменять поведение по умолчанию, предоставляя один или несколько специальных методов:
Изменено в версии 3.6: __getnewargs_ex__() теперь используется в протоколах 2 и 3.
Изменено в версии 3.6: До Python 3.6 __getnewargs__() вызывался вместо __getnewargs_ex__() в протоколах 2 и 3.
object. __setstate__ ( state ) ¶
Если __getstate__() возвращает a false значение, метод __setstate__() не будет вызываться при откате.
В настоящее время интерфейс определяется следующим образом. Метод __reduce__() не берет аргумента, и будет возвращает или строка или предпочтительно кортеж (объект возвращенный часто упоминается, поскольку «уменьшают значение»).
Если строка является возвращенный, то строка следует интерпретировать как имя глобальной переменной. Это должно быть имя локальная объекта относительно своего модуля; модуль pickle выполняет поиск пространства имен модулей для определения модуля объекта. Это поведение обычно полезно для синглтонов.
Вызываемый объект, который будет вызван для создания начальной версии объекта.
Кортеж аргументов для вызываемого объекта. Если вызываемый объект не принимает какой-либо аргумент, необходимо указать пустой кортеж.
При необходимости, состояние объекта, который будет передан методу __setstate__() объекта, как описано выше. Если объект не имеет такого метода, то значение должен быть словарем и будет добавлен в __dict__ атрибут объекта.
Сохранение внешних объектов¶
В интересах сохранения объекта модуль pickle поддерживает понятие ссылки на объект вне потока pickled данных. На такие объекты ссылается постоянный идентификатор, который должен быть либо строка буквенно-цифровых символов (для протокола 0) [5], либо просто произвольным объектом (для любого нового протокола).
Разрешение таких постоянных идентификаторов не определяется модулем pickle ; он делегирует это разрешение определяемым пользователем методам на отборщике и распаковщике, persistent_id() и persistent_load() соответственно.
Вот всестороннее представление в качестве примера, как настойчивый ID может быть используемый к внешним объектам pickle ссылкой.
Таблицы диспетчеризации¶
Если требуется настроить пиклинг некоторых классов, не нарушая никакой другой код, которая зависит от пиклинг, то можно создать селектор с частной таблицей диспетчеризации.
Обработка объектов с учетом состояния¶
Образец использования может быть примерно таким:
Пользовательское сокращение для типов, функций и других объектов¶
Добавлено в версии 3.8.
Иногда dispatch_table может быть недостаточно гибким. В частности, может потребоваться настроить пиклинг на основе другого критерия, отличного от типа объекта, или настроить пиклинг функций и классов.
Вот простой пример, где мы допускаем пиклинг и реконструкцию данного класса:
Внеполосные буферы¶
Добавлено в версии 3.8.
Этого ограничения можно сторониться, если оба поставщик (внедрение типов объекта, которые будут переданы) и потребитель (внедрение коммуникационных систем), поддерживают услуги передачи из группы, предоставленные протоколом 5 pickle и выше.
API поставщика¶
Потребительский API¶
На принимающей стороне он должен передать аргумент buffers Unpickler (или функции load() или loads() ), который является итерабельным из буферов, которые были переданы buffer_callback. Эта итерабельность должна давать буферы в том же порядке, в каком они были переданы buffer_callback. Эти буферы будут предоставлять данные, ожидаемые реконструкторами объектов, чьи пиклинг создали исходные PickleBuffer объекты.
Между передающей стороной и принимающей стороной система связи может свободно реализовывать свой собственный механизм передачи для внеполосных буферов. Потенциальные оптимизации включают использование общей памяти или сжатие, зависящее от типа данных.
Пример¶
Вот тривиальный пример, где мы реализуем bytearray подкласс, способный участвовать во внеполосных буферных пиклинг:
reconstructor (метод класса _reconstruct ) возвращает обеспечение буфера объекта, если у этого есть правильный тип. Это простой способ имитировать поведение нулевой копии на этом примере игрушки.
На стороне потребителя мы можем pickle эти объекты обычным способом, который при несериализации даст нам копию оригинального объекта:
Но если мы передадим buffer_callback, а затем отдадим накопленные буферы при несериализации, мы сможем вернуть исходный объект:
Этот пример ограничен тем, что bytearray выделяет собственную память: нельзя создать bytearray сущность, поддерживаемую памятью другого объекта. Однако сторонние типы данных, такие как множества NumPy не имеют этого ограничения и позволяют использование нулевой копии пиклинг (или делающий как можно меньше копий), переходя между отличными процессами или системами.
Ограничение Globals¶
По умолчанию отмена выбора приведет к импорту любого класса или функции, найденных в pickle данных. Во многих случаях такое поведение неприемлемо, поскольку позволяет нарушителю импортировать и использовать произвольные код. Просто рассмотрите то, что это изготовило вручную поток данных pickle, делает, когда он загружен:
Вот пример открепителя, позволяющего загрузить только несколько безопасных классов из модуля builtins :
Образец использования нашей работы unpickler предназначался:
Как показывают наши примеры, вы должны быть осторожны с тем, что вы позволяете быть unpickled. Поэтому, если безопасность является проблемой, может потребоваться рассмотреть альтернативные варианты, такие как API-интерфейс сортировки в решениях xmlrpc.client или сторонних производителей.
Исполнение¶
Последние версии протокола pickle (от протокола 2 и выше) имеют эффективные двоичные кодировки для нескольких общих функций и встроенных типов. Кроме того, модуль pickle имеет прозрачный оптимизатор, написанный на C.
Примеры¶
Для простейших код используйте функции dump() и load() :
В следующем примере считываются результирующие данные pickled: