Модуль Pickle в Python
В разработке на Python нам часто нужно сохранять объекты времени выполнения или восстанавливать предыдущее состояние после перезапуска программы, например:
- Кэшировать результаты вычислений на диск, чтобы избежать повторных вычислений
- Сохранять пользовательскую конфигурацию и промежуточное состояние программы
- Передача сложных объектов между разными процессами Python
pickleМодуль — это то, что Python предоставляет для решения этих задачОфициальное встроенное решение。
Pythonpickleмодуль — это модуль стандартной библиотеки для сериализации и десериализации объектов Python.
Прежде чем начать использовать Pickle, нужно понять две ключевые концепции:
- Сериализация (Pickling): преобразование объектов Python в последовательности байтов
- Десериализация (Unpickling): преобразование последовательностей байтов обратно в объекты Python
pickleМодуль может сохранять почти все объекты Python (например, списки, словари, экземпляры классов и т. д.) в файлы, передавать их по сети, а затем при необходимости загружать обратно.
Зачем использовать модуль Pickle?
- Сохранение данных: сохранение объектов Python в файлы, чтобы данные оставались доступными после закрытия программы.
- Передача данных: передача объектов Python по сети, например, передача данных в распределённых системах.
- Быстрое сохранение и загрузка:
pickleМодуль может эффективно обрабатывать сложные структуры данных и подходит для сценариев, требующих быстрого сохранения и загрузки.
Типичные сценарии использования Pickle
pickleОн очень хорошо подходит для следующих сценариев:
- Локальное сохранение данных
- Сохранение и восстановление состояния выполнения программы
- Кэширование промежуточных результатов вычислений
- Межпроцессное взаимодействие Python (IPC)
- Сохранение моделей машинного обучения и данных признаков
Неподходящие сценарии:
- Обмен данными между языками
- Передача данных через интерфейс между фронтендом и бэкендом
- Десериализация недоверенных источников данных
Какие объекты поддерживает Pickle?
1. Поддерживаемые типы объектов
| Type | Поддерживается? |
|---|---|
| int / float / bool / str | Поддерживается |
| list / tuple / dict / set | Поддерживается |
| Отсутствует | Поддерживается |
| Экземпляры пользовательских классов | Поддерживается |
| Вложенные структуры | Поддерживается |
Неподдерживаемые или нерекомендуемые объекты
- Открытые файловые объекты
- socket, подключения к базам данных
- Ресурсы операционной системы
- Объекты, зависящие от состояния среды выполнения
Импорт модуля
Использование модуля Pickle очень просто: достаточно импортировать его:
import pickle
Базовое использование модуля Pickle
1. Сериализация объектов
Используйтеpickle.dump()метод может сериализовать объекты Python и сохранить их в файл.
Пример
# Создайте объект Python
data = {
'name': 'Alice',
'age': 25,
'hobbies': ['reading', 'traveling']
}
# Сериализуйте объект и сохраните его в файл
with open('data.pkl', 'wb') as файл:
pickle.dump(data, file)
'wb'Указывает на открытие файла в режиме двоичной записи.pickle.dump()будетdataОбъект сериализуется и записывается в файл.
2. Десериализация объектов
Используйтеpickle.load()метод может загружать и десериализовать объекты Python из файла.
Пример
# Загрузка и десериализация объектов из файла
with open('data.pkl', 'rb') as файл:
loaded_data = pickle.load(file)
print(loaded_data)
'rb'Указывает на открытие файла в режиме бинарного чтения.pickle.load()Считывает поток байтов из файла и десериализует его в объект Python.
3. Сериализация в байтовую строку
Если вы не хотите сохранять в файл, можно использовать pickle.dumps() для сериализации объекта в байтовую строку:
Пример
data = [1, 2, 3, 4, 5]
# Сериализация в байтовую строку
byte_data = pickle.dumps(data)
print(byte_data)
# Вывод примерно такой: b'\x80\x04\x95\x0f\x00\x00\x00...'
4. Десериализация из байтовой строки
Используйте pickle.loads() для десериализации объектов из байтовой строки:
Пример
byte_data = b'\x80\x04\x95\x0f\x00\x00\x00\x00\x00\x00\x00]\x94(K\x01K\x02K\x03K\x04K\x05e.'
# Десериализация из байтовой строки
original_data = pickle.loads(byte_data)
print(original_data)
# Вывод: [1, 2, 3, 4, 5]
5. Типы объектов, которые можно сериализовать
Pickle может сериализовать большинство объектов Python, включая:
- Базовые типы данных: целые числа, числа с плавающей запятой, строки, логические значения, None
- Типы коллекций: списки, кортежи, словари, множества
- Экземпляры пользовательских классов
- Функции и классы (с определёнными ограничениями)
Пример
# Сериализовать различные типы данных
numbers = [1, 2, 3]
text = "Hello, Pickle"
dictionary = {'key': 'value'}
tuple_data = (1, 2, 3)
set_data = {1, 2, 3}
# Поместить все данные в список
all_data = [numbers, text, dictionary, tuple_data, set_data]
# Сериализовать
with open('mixed_data.pkl', 'wb') as f:
pickle.dump(all_data, f)
# Десериализовать
with open('mixed_data.pkl', 'rb') as f:
loaded_data = pickle.load(f)
print(loaded_data)
6. Сериализация пользовательских классов
Pickle хорошо справляется с экземплярами пользовательских классов:
Пример
class Student:
def __init__(self, name, age, grade):
self.name = name
self.age = age
self.grade = grade
def __repr__(self):
return f"Student(name={self.name}, age={self.age}, grade={self.grade})"
# Создать экземпляр
student = Student("Li Si", 20, "Junior")
# Сериализовать
with open('student.pkl', 'wb') as f:
pickle.dump(student, f)
# Десериализовать
with open('student.pkl', 'rb') as f:
loaded_student = pickle.load(f)
print(loaded_student)
# Вывод: Student(name=Li Si, age=20, grade=Junior)
7. Сериализация нескольких объектов
Вы можете вызвать pickle.dump() несколько раз, чтобы сохранить несколько объектов:
Пример
data1 = {'item': 'apple', 'count': 5}
data2 = ['banana', 'orange', 'grape']
data3 = 42
# Сохранить несколько объектов
with open('multiple.pkl', 'wb') as f:
pickle.dump(data1, f)
pickle.dump(data2, f)
pickle.dump(data3, f)
# Чтение нескольких объектов (порядок должен быть согласован)
with open('multiple.pkl', 'rb') as f:
loaded_data1 = pickle.load(f)
loaded_data2 = pickle.load(f)
loaded_data3 = pickle.load(f)
print(loaded_data1)
print(loaded_data2)
print(loaded_data3)
8. Примеры практического применения
Пример 1: Сохранение и загрузка конфигурации модели машинного обучения
Пример
# Имитация конфигурации модели машинного обучения
model_config = {
'model_type': 'RandomForest',
'n_estimators': 100,
'max_depth': 10,
'trained_date': '2024-01-13',
'accuracy': 0.95
}
# Сохранить конфигурацию
with open('model_config.pkl', 'wb') as f:
pickle.dump(model_config, f)
# Загрузить конфигурацию
with open('model_config.pkl', 'rb') as f:
config = pickle.load(f)
print(f"Тип модели: {config['model_type']}")
print(f"Точность: {config['accuracy']}")
Пример 2: Кэширование результатов вычислений
Пример
import os
def expensive_computation(n):
"""Имитировать длительное вычисление"""
result = sum(i ** 2 for i in range(n))
return result
def compute_with_cache(n, cache_file='cache.pkl'):
# Проверить, существует ли кэш
if os.path.exists(cache_file):
with open(cache_file, 'rb') as f:
cache = pickle.load(f)
if n in cache:
print("Результат прочитан из кэша")
return cache[n]
else:
cache = {}
# Выполнить вычисление
print("Выполняется расчёт...")
result = expensive_computation(n)
# Сохранить в кэш
cache[n] = result
with open(cache_file, 'wb') as f:
pickle.dump(cache, f)
return result
# Пример использования
print(compute_with_cache(1000000)) # При первом вызове будет вычислено
print(compute_with_cache(1000000)) # Во второй раз будет прочитано из кэша
Примечания о модуле Pickle
- Безопасность:
pickleМодуль исполняет произвольный код во время десериализации, поэтому не загружайтеpickleданные из ненадёжных источников, чтобы избежать вредоносных атак. - Совместимость:
pickleСгенерированный поток байтов специфичен для Python, и могут возникнуть проблемы совместимости между разными версиями Python. - Производительность: Для больших наборов данных,
pickleсериализация и десериализация могут быть относительно медленными; можно рассмотреть использование более эффективных инструментов сериализации, таких какjsonилиmsgpack。
Расширенное использование: сериализация пользовательских объектов
pickleМодуль поддерживает сериализацию пользовательских классов. По умолчанию,pickleон сохраняет атрибуты объекта и имя класса. Если вам нужна более сложная логика сериализации, вы можете реализовать__getstate__()и__setstate__()методы.
Пример
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __getstate__(self):
# Пользовательская логика сериализации
return {'name': self.name, 'age': self.age}
def __setstate__(self, state):
# Пользовательская логика десериализации
self.name = state['name']
self.age = state['age']
# Создать объект и сериализовать
person = Person('Bob', 30)
with open('person.pkl', 'wb') as файл:
pickle.dump(person, file)
# Десериализовать объект
with open('person.pkl', 'rb') as файл:
loaded_person = pickle.load(file)
print(loaded_person.name, loaded_person.age)
Общие методы модуля pickle
| Метод | Описание | Пример |
|---|---|---|
pickle.dump(obj, file) | Сериализовать объект и записать в файл | pickle.dump(data, open('data.pkl', 'wb')) |
pickle.load(file) | Прочитать из файла и десериализовать объект | data = pickle.load(open('data.pkl', 'rb')) |
pickle.dumps(obj) | Сериализовать объект в байтовую строку | bytes_data = pickle.dumps([1, 2, 3]) |
pickle.loads(bytes) | Десериализовать объект из байтовой строки | lst = pickle.loads(bytes_data) |
pickle.HIGHEST_PROTOCOL | Наивысшая доступная версия протокола (атрибут) | pickle.dump(..., protocol=pickle.HIGHEST_PROTOCOL) |
pickle.DEFAULT_PROTOCOL | Версия протокола по умолчанию (атрибут, обычно 4) | pickle.dumps(obj, protocol=pickle.DEFAULT_PROTOCOL) |
1. Сериализация объекта в файл
Пример
data = {'name': 'Alice', 'age': 25}
with open('data.pkl', 'wb') as f:
pickle.dump(data, f, protocol=pickle.HIGHEST_PROTOCOL)
2. Десериализация из файла
Пример
loaded_data = pickle.load(f)
print(loaded_data) # Вывод: {'name': 'Alice', 'age': 25}
3. Сериализация в байтовую строку (передача по сети/кэш)
Пример
restored_list = pickle.loads(bytes_data)
Версии протокола модуля pickle
| Версия протокола | Описание |
|---|---|
| 0 | Удобочитаемый формат ASCII (совместим с более старыми версиями) |
| 1 | Двоичный формат (совместим с более старыми версиями) |
| 2 | Python 2.3+: оптимизированная поддержка объектов классов |
| 3 | Python 3.0+: протокол по умолчанию (не поддерживается в Python 2) |
| 4 | Python 3.4+: поддерживает более крупные объекты и больше типов данных |
| 5 | Python 3.8+: поддерживает оптимизацию памяти и совместное использование данных |