Введение в модуль Python Pickle

Введение Маринование - популярный метод консервирования продуктов. Согласно Википедии [https://en.wikipedia.org/wiki/Pickling], это тоже довольно древняя процедура - хотя происхождение маринования неизвестно, древние месопотамцы, вероятно, использовали этот процесс 4400 лет назад. Поместив продукт в определенный раствор, можно резко увеличить срок его хранения. Другими словами, это метод, который позволяет нам хранить пищу для последующего употребления. Если вы разработчик Python, вы можете

Вступление

Маринование - популярный способ консервирования продуктов. Согласно Википедии , это также довольно древняя процедура - хотя происхождение маринования неизвестно, древние месопотамцы, вероятно, использовали этот процесс 4400 лет назад. Поместив продукт в определенный раствор, можно резко увеличить срок его хранения. Другими словами, это метод, который позволяет нам хранить пищу для последующего употребления.

Если вы разработчик Python, однажды вам может понадобиться способ хранения ваших объектов Python для последующего использования. Что, если бы я сказал вам, что вы тоже можете мариновать объекты Python?

Сериализация

Сериализация - это процесс преобразования объектов или структур данных в байтовые потоки или строки. Байтовый поток - это, в общем, поток байтов - один байт состоит из 8 бит нулей и единиц. Эти байтовые потоки затем можно легко сохранить или передать. Это позволяет разработчикам сохранять, например, данные конфигурации или прогресс пользователя, а затем сохранять их (на диске или в базе данных) или отправлять в другое место.

Объекты Python также можно сериализовать с помощью модуля под названием Pickle .

Одно из основных различий между маринованием объектов Python и маринованием овощей - это неизбежное и необратимое изменение вкуса и текстуры маринованной пищи. Между тем, маринованные объекты Python можно легко вернуть в исходную форму. Кстати, этот процесс широко известен как десериализация .

Травление (или сериализацию в целом) не следует путать со сжатием. Целью травления является перевод данных в формат, который может быть перенесен из ОЗУ на диск. С другой стороны, сжатие - это процесс кодирования данных с использованием меньшего количества бит (для экономии места на диске).

Сериализация особенно полезна в любом программном обеспечении, где важно иметь возможность сохранить некоторый прогресс на диске, выйти из программы, а затем снова загрузить прогресс после повторного открытия программы. Видеоигры могут быть наиболее интуитивным примером полезности сериализации, но есть много других программ, в которых сохранение и загрузка данных или прогресса пользователя имеет решающее значение.

Рассол против JSON

Есть шанс, что вы слышали о JSON (нотация объектов JavaScript), который является популярным форматом, который также позволяет разработчикам сохранять и передавать объекты, закодированные в виде строк. Этот метод сериализации имеет некоторые преимущества перед травлением. Формат JSON удобочитаем, не зависит от языка и быстрее, чем pickle.

Однако у него есть и некоторые важные ограничения. Что наиболее важно, по умолчанию только ограниченное подмножество встроенных типов Python может быть представлено JSON. С помощью Pickle мы можем легко сериализовать очень широкий спектр типов Python и, что важно, настраиваемые классы. Это означает, что нам не нужно создавать настраиваемую схему (как мы делаем для JSON) и писать сериализаторы и парсеры, подверженные ошибкам. С Pickle вся тяжелая работа будет сделана за вас.

Что можно мариновать и не мариновать

Следующие типы можно сериализовать и десериализовать с помощью модуля Pickle:

  • Все собственные типы данных, поддерживаемые Python (логические, None, целые числа, числа с плавающей запятой, комплексные числа, строки, байты, байтовые массивы)
  • Словари, наборы, списки и кортежи - если они содержат выбираемые объекты
  • Функции и классы, определенные на верхнем уровне модуля

Важно помнить, что травление не является независимым от языка методом сериализации, поэтому ваши консервированные данные могут быть извлечены только с помощью Python. Более того, важно убедиться, что объекты обрабатываются с использованием той же версии Python, которая будет использоваться для их выделения . В этом случае смешивание версий Python может вызвать множество проблем.

Кроме того, функции выбираются по ссылкам на их имена, а не по их значению. Полученный в результате рассол не содержит информации о коде или атрибутах функции. Следовательно, вы должны убедиться, что среда, в которой функция не выбрана, может импортировать функцию. Другими словами, если мы выберем функцию, а затем удалим ее в среде, где она либо не определена, либо не импортирована, возникнет исключение.

Также очень важно отметить, что маринованные предметы могут использоваться злонамеренно. Например, извлечение данных из ненадежного источника может привести к выполнению вредоносного кода.

Сбор списка Python

В следующем очень простом примере показаны основы использования модуля Pickle в Python 3 :

 import pickle 
 
 test_list = ['cucumber', 'pumpkin', 'carrot'] 
 
 with open('test_pickle.pkl', 'wb') as pickle_out: 
 pickle.dump(test_list, pickle_out) 

Во-первых, мы должны импортировать pickle , что выполняется в строке

  1. В строке 3 мы определяем простой список из трех элементов, который будет обработан.

В строке 5 мы указываем, что имя нашего выходного файла рассола будет test_pickle.pkl . Используя параметр wb , мы сообщаем программе, что хотим записать ( w ) двоичные данные ( b ) внутри нее (потому что мы хотим создать поток байтов). Обратите внимание, что pkl не обязательно

  • мы используем его в этом руководстве, потому что это расширение включено в документацию Python.

В строке 6 мы используем метод pickle.dump() чтобы собрать наш тестовый список и сохранить его в файле test_pickle.pkl

Я рекомендую вам попробовать открыть сгенерированный файл рассола в текстовом редакторе. Вы быстро заметите, что поток байтов определенно не является удобочитаемым форматом.

Распаковка списка Python

Теперь давайте раскроем содержимое тестового файла pickle и вернем наш объект к его исходной форме.

 import pickle 
 
 with open('test_pickle.pkl', 'rb') as pickle_in: 
 unpickled_list = pickle.load(pickle_in) 
 
 print(unpickled_list) 

Как видите, эта процедура не сложнее, чем когда мы мариновали объект. В строке 3 мы test_pickle.pkl , но на этот раз наша цель - прочитать ( r ) двоичные данные ( b ), хранящиеся в нем.

Затем, в строке 5, мы используем метод pickle.load() чтобы распаковать наш список и сохранить его в переменной unpickled_list

Затем вы можете распечатать содержимое списка, чтобы убедиться, что он идентичен списку, который мы выбрали в предыдущем примере. Вот результат выполнения приведенного выше кода:

 $ python unpickle.py 
 ['cucumber', 'pumpkin', 'carrot'] 

Травление и распаковка пользовательских объектов

Как я упоминал ранее, используя Pickle, вы можете сериализовать свои собственные настраиваемые объекты. Взгляните на следующий пример:

 import pickle 
 
 class Veggy(): 
 def __init__(self): 
 self.color = '' 
 def set_color(self, color): 
 self.color = color 
 
 cucumber = Veggy() 
 cucumber.set_color('green') 
 
 with open('test_pickle.pkl', 'wb') as pickle_out: 
 pickle.dump(cucumber, pickle_out) 
 
 with open('test_pickle.pkl', 'rb') as pickle_in: 
 unpickled_cucumber = pickle.load(pickle_in) 
 
 print(unpickled_cucumber.color) 

Как видите, этот пример почти такой же простой, как и предыдущий. Между строками 3 и 7 мы определяем простой класс, который содержит один атрибут и один метод, который изменяет этот атрибут. В строке 9 мы создаем экземпляр этого класса и сохраняем его в cucumber , а в строке 10 мы устанавливаем color его атрибута на «зеленый».

Затем, используя те же функции, что и в предыдущем примере, мы солим и отделяем наш только что созданный объект cucumber Выполнение приведенного выше кода приводит к следующему выводу:

 $ python unpickle_custom.py 
 green 

Помните, что мы можем распаковать объект только в среде, где класс Veggy либо определен, либо импортирован. Если мы создадим новый скрипт и попытаемся выделить объект без импорта Veggy , мы получим «AttributeError». Например, выполните следующий сценарий:

 import pickle 
 
 with open('test_pickle.pkl', 'rb') as pickle_in: 
 unpickled_cucumber = pickle.load(pickle_in) 
 
 print(unpickled_cucumber.color) 

В выводе приведенного выше скрипта вы увидите следующую ошибку:

 $ python unpickle_simple.py 
 Traceback (most recent call last): 
 File "<pyshell#40>", line 2, in <module> 
 unpickled_cucumber = pickle.load(pickle_in) 
 AttributeError: Can't get attribute 'Veggy' on <module '__main__' (built-in)> 

Заключение

Как видите, благодаря модулю Pickle сериализация объектов Python довольно проста. В наших примерах мы выбрали простой список Python - но вы можете использовать тот же метод для сохранения большого спектра типов данных Python, если вы убедитесь, что ваши объекты содержат только другие выбираемые объекты.

У Pickling есть некоторые недостатки, самый большой из которых может заключаться в том, что вы можете распаковать свои данные только с помощью Python - если вам нужно кросс-языковое решение, JSON определенно лучший вариант. И, наконец, помните, что соленые огурцы можно использовать для переноса кода, который вы не обязательно хотите выполнять. Как и в случае с маринованными продуктами, если вы получаете соленья из проверенных источников, все будет в порядке.

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus