9.1 Знайомство з pickle

Модуль pickle дозволяє зберегти практично будь-який об'єкт Python у файл або рядок, а потім відновити його до вихідного стану. pickle підтримує багато типів даних, включаючи користувацькі об'єкти класів, і автоматизує процес перетворення об'єктів у байтовий формат і назад.

Основні функції модуля pickle

  • Читання і запис об'єкта у файл
    • pickle.dump(obj, file): Сеаріалізує об'єкт obj і записує його в відкритий файл file.
    • pickle.load(file): Зчитує з файлу file і десеаріалізує об'єкт.
  • Читання і запис об'єкта в масив байт
    • pickle.dumps(obj): Сеаріалізує об'єкт obj і повертає його як байтовий об'єкт.
    • pickle.loads(bytes): Десеаріалізує об'єкт з байтового об'єкта.

Нижче ми розглянемо їх трохи детальніше:

9.2 Сеаріалізація у файл

Основні кроки сеаріалізації у файл:

  1. Відкриття файлу в режимі запису байтів (wb).
  2. Сеаріалізація об'єкта за допомогою pickle.dump(obj, file).
  3. Для десеаріалізації об'єкта використовуємо pickle.load(file).
  4. Закриття файлу.

Сеаріалізація і десеаріалізація об'єкта у файл

В принципі pickle все одно, що сеаріалізувати. Наприклад, так виглядає сеаріалізація списку:


import pickle

data = [1, 2, 3, 4, 5]

# Сеаріалізація списку у файл
with open('list.pkl', 'wb') as file:
    pickle.dump(data, file)

# Десеаріалізація списку з файлу
with open('list.pkl', 'rb') as file:
    loaded_data = pickle.load(file)

print(loaded_data)  # Вивід: [1, 2, 3, 4, 5]

А ось так виглядає сеаріалізація об'єкта словника:


import pickle

# Приклад об'єкта для сеаріалізації
data = {'name': 'Alice', 'age': 30, 'is_student': False}

# Сеаріалізація об'єкта у файл
with open('data.pkl', 'wb') as file:
    pickle.dump(data, file)

# Десеаріалізація об'єкта з файлу
with open('data.pkl', 'rb') as file:
    loaded_data = pickle.load(file)

print(loaded_data)  # Вивід: {'name': 'Alice', 'age': 30, 'is_student': False}

Хочемо зберегти об'єкт — викликаємо dump(), хочемо завантажити — викликаємо load(). Нічого складного.

9.3 Сеаріалізація в рядок

Дуже часто об'єкти потрібно передати по мережі, тому об'єкт потрібно зберегти не у файл, а в рядок. Для цього у pickle є методи dumps і loads з додатковою s на кінці.

Основні дії для сеаріалізації і десеаріалізації в рядок (або масив байт):

  • Сеаріалізація об'єкта за допомогою pickle.dumps(obj).
  • Для десеаріалізації об'єкта використовуємо pickle.loads(data).

Сеаріалізація і десеаріалізація об'єкта в рядок

Сеаріалізація об'єкта в рядок (або набір байт) ще простіше — вам потрібно викликати один метод — dumps().

Приклад:


import pickle

# Приклад об'єкта для сеаріалізації
data = {'name': 'Bob', 'age': 25, 'is_student': True}

# Сеаріалізація об'єкта в рядок
serialized_data = pickle.dumps(data)
print(serialized_data)

# Десеаріалізація об'єкта з рядка
loaded_data = pickle.loads(serialized_data)
print(loaded_data)  # Вивід: {'name': 'Bob', 'age': 25, 'is_student': True}

9.4 Помилки при сеаріалізації

Іноді при сеаріалізації виникають помилки. У цьому випадку модуль pickle буде кидати виключення:

  • pickle.PicklingError — помилка під час сеаріалізації.
  • pickle.UnpicklingError — помилка під час десеаріалізації.

Приклади:


import pickle

data = {'key': 'value'}

try:
    # Сеаріалізація об'єкта у файл
    with open('data.pkl', 'wb') as file:
        pickle.dump(data, file)
except pickle.PicklingError as e:
    print(f"Помилка сеаріалізації: {e}")

try:
    # Десеаріалізація об'єкта з файлу
    with open('data.pkl', 'rb') as file:
        loaded_data = pickle.load(file)
    print(loaded_data)
except pickle.UnpicklingError as e:
    print(f"Помилка десеаріалізації: {e}")

Зазвичай ви як програміст нічого не можете зробити з помилкою сеаріалізації/десеаріалізації під час роботи програми. Все, що ви можете — це зберегти її в лог, щоб у майбутньому розібратися, чому ж це сталося.

Основна причина таких помилок — це зміна формату об'єкта. Ви зберегли об'єкт у файл, потім ваша програма оновилася, і у об'єкта з'явилися нові поля або зникли старі. І ось старий збережений об'єкт намагаються завантажити в клас нового об'єкта…

Знову ж таки, ця ситуація часто зустрічається при роботі з мережею — програма версії 2.18 відсилає трохи не той об'єкт, який чекає програма версії 3.1. Це називається проблема міграції, і з нею дуже часто стикаються в довготривалих і популярних проектах.