Почему pickle.dumps(lambda x: x*2) вызывает ошибку

Почему pickle.dumps(lambda x: x*2) вызывает ошибку

@python_quiz

Разберем этот квиз

Кратко: попытка сериализовать лямбда-функцию через стандартный модуль pickle не проходит — возникает исключение PicklingError. Ниже объясню почему, покажу демонстрацию и предложу рабочие альтернативы.

Условие задачи

Дан код:

python

Нужно понять, что произойдёт при выполнении и почему.

Что происходит и почему

pickle сериализует объекты, сохраняя их состояние или ссылку на объект. Для функций стандартный pickle не сериализует «тело» функции — он сохраняет ссылку на функцию через модуль и имя (qualified name). При десериализации pickle пытается найти эту функцию в модуле по имени.

Лямбда-функции не имеют устойчивого имени в модуле (они анонимны и часто считаются локальными объектами), поэтому pickle не может представить ссылку на них. В результате возникает исключение, относящееся к механизму сериализации — pickle.PicklingError.

Демонстрация

Пример, показывающий поведение в реальной Python-сессии:

python

Ожидаемый вывод (пример):

Для сравнения: именованная (модульная) функция сериализуется как ссылка без ошибок:

python

Анализ возможных вариантов ответа

  • "Выведет: OK" — неверно: pickle.dumps(lambda...) не вернёт "OK" и не завершится успешно.
  • "Выведет: PicklingError" — это поведение, которое действительно наблюдается: pickle не может сериализовать лямбды и выбрасывает pickle.PicklingError.
  • "Выведет: AttributeError" — неверно: исключение непосредственно от pickle в данном случае — PicklingError; хотя внутри сообщения может упоминаться проблема с атрибутом, сам тип исключения — не AttributeError.
  • "Выведет: ValueError" — неверно: ValueError не используется pickle для этой ситуации.

Что делать, если нужно сериализовать лямбды

Если вам действительно нужно сериализовать анонимные или локальные функции, есть варианты:

  1. Использовать библиотеки, которые умеют сериализовать код и замыкания:

- cloudpickle
- dill

Пример с cloudpickle:

python
  1. Переписать функцию как именованную на уровне модуля (preferred для простоты и ясности):
python
  1. Для распределённых вычислений использовать специализированные механизмы (например, отправлять код как текст и выполнять через exec, хранить параметры вместо функций и т.д.), но это требует осторожности с безопасностью.

Вывод

Стандартный модуль pickle не сериализует лямбда-функции — попытка pickle.dumps(lambda ...) приводит к pickle.PicklingError. Для сериализации анонимных или локальных функций используйте cloudpickle/dill или определяйте функции на уровне модуля.

Report Page