Распакуйте cloudpickle без установки cloudpickle
Модуль
По умолчанию pickle
из стандартной библиотеки Python не допускает сериализации функций с замыканиями, лямбдами или функциями в __main__
(см.здесь ).
Мне нужно замариновать объект, используя некоторые пользовательские функции, которые не будут импортироваться там, где они будут распакованы. Есть несколько других сериализаторов объектов Python, включая dill
и cloudpickle
, которые способны сделать это.
cloudpickle
документация , кажется, говорит, что даже если вы маринуете с помощью cloudpickle
, Вы можете распаковать с помощью стандартного модуля pickle
. Это чрезвычайно привлекательно, потому что я не могу даже установить пакеты в среде, где мне нужно распаковывать.
Действительно, пример в документации делает в основном следующее:
Рассольник:
>>> import cloudpickle
>>> squared = lambda x: x ** 2
>>> pickled_lambda = cloudpickle.dump(squared, open('pickled_file', 'w'))
Unpickle:
>>> import pickle
>>> new_squared = pickle.load(open('pickled_file', 'rb'))
>>> new_squared(2)
Но запуск этого второго блока в среде, где cloudpickle
не установлен, даже если он никогда не импортируется, дает ошибка:
"ImportError: No module named cloudpickle.cloudpickle"
Вероятно, наиболее легко воспроизводимым примером будет установка cloudpickle
для Python2, запуск первого блока, а затем попытка загрузить в маринованный файл второй блок с помощью Python3 (где cloudpickle
не был установлен).
Что здесь происходит? Почему cloudpickle
должен быть установлен для запуска стандартной загрузки pickle
, если он даже не вызывается?
1 ответ:
Теоретически,
cloudpickle
не нужно устанавливать наload
маринованный объект. Теоретически, то, чтоcloudpickle
будет делать, будет также включать все функции, необходимые для распаковки объекта внутри этого объекта. Впрочем, это в теории.В реестре методов (например, с помощью
copyreg
) сериализатор должен зарегистрировать метод, который позволяет сериализатору создать новый объект требуемого типа и наполнить его сохраненным состоянием. Чтобы сериализатор не требовалось устанавливать на при загрузке сериализатор должен будет включить все необходимые методы десериализации в сам маринованный объект (это возможно, поскольку маринование рекурсивно).
cloudpickle
предполагается, чтоcloudpickle
установлен, и поэтому (чтобы сделать полученный маринованный объект меньше), не включает все необходимые методы. Это не похоже наnumpy
, в качестве контрпримера, который методdumps
наnumpy.array
включает методreconstruct
в рассоле (вы можете видеть это, посколькуnumpy.core.multiarray\n_reconstruct
появляется в любом маринованный огурецarray
).