在没有cloudpickle安装的情况下取消一个cloudpickle

时间:2016-03-09 20:07:02

标签: python pickle

Python标准库中的默认pickle模块不允许使用__main__中的闭包,lambdas或函数对函数进行序列化(请参阅here)。

我需要使用一些自定义函数来挑选一个对象,这些函数在它们将被打开的情况下是不可导入的。还有一些其他Python对象序列化程序,包括dillcloudpickle,它们能够执行此操作。

cloudpickle documentation似乎在说,即使您使用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"

可能最容易重现的示例可能是为Python2安装cloudpickle,运行第一个块,然后尝试使用Python3加载第二个块的pickle文件(其中cloudpickle不是安装)。

这里发生了什么?如果甚至没有调用标准cloudpickle加载,为什么需要安装pickle

1 个答案:

答案 0 :(得分:1)

理论上,cloudpickle不需要安装到load一个腌制对象。从理论上讲,cloudpickle所做的也包括在该对象中取消对象的所有必要功能。但是,这是理论上的。

在方法注册表中(例如,使用copyreg),序列化程序需要注册使串行器能够创建所需类型的新对象并使其保存状态的方法。对于不需要在加载时安装序列化程序,序列化程序需要在pickle对象本身中包含所有必需的反序列化方法(这是可能的,因为pickle是递归的)。

cloudpickle假定已安装cloudpickle,因此(为了使生成的pickled对象更小),不包括所有必需的方法。这与numpy不同,作为反例,dumps上的numpy.array方法确实包含了pickle中的reconstruct方法(您可以将其视为{{ 1}}出现在numpy.core.multiarray\n_reconstruct)的任何泡菜中。