Python 在未安装cloudpickle的情况下解除对cloudpickle的粘贴
Python标准库中的默认Python 在未安装cloudpickle的情况下解除对cloudpickle的粘贴,python,pickle,Python,Pickle,Python标准库中的默认pickle模块不允许使用闭包、lambda或\uuuuuu main\uuuuuu中的函数进行序列化(请参阅) 我需要使用一些自定义函数来pickle一个对象,这些自定义函数在取消pickle的地方是不可导入的。还有一些其他的Python对象序列化程序,包括dill和cloudpickle,能够完成这项工作 cloudpickle似乎在说,即使使用cloudpickle进行pickle,也可以使用标准的pickle模块取消pickle。这非常有吸引力,因为我甚至不能在
pickle
模块不允许使用闭包、lambda或\uuuuuu main\uuuuuu
中的函数进行序列化(请参阅)
我需要使用一些自定义函数来pickle一个对象,这些自定义函数在取消pickle的地方是不可导入的。还有一些其他的Python对象序列化程序,包括dill
和cloudpickle
,能够完成这项工作
cloudpickle
似乎在说,即使使用cloudpickle
进行pickle,也可以使用标准的pickle
模块取消pickle。这非常有吸引力,因为我甚至不能在需要解压的环境中安装软件包
实际上,文档中的示例基本上实现了以下功能:
泡菜:
解钩:
但是,在未安装cloudpickle
的环境中运行第二个块,即使从未导入,也会产生错误:
"ImportError: No module named cloudpickle.cloudpickle"
最容易复制的示例可能是为Python2安装cloudpickle
,运行第一个块,然后尝试使用Python3将第二个块加载到pickle文件中(其中未安装cloudpickle
)
这是怎么回事?如果标准的
pickle
加载甚至没有被调用,为什么需要安装cloudpickle
来运行它?理论上,cloudpickle
不需要安装到load
一个pickle对象。从理论上讲,cloudpickle
所能做的就是包含所有必要的函数,以便在该对象中取消勾选对象。然而,这是理论上的
在方法注册表中(例如,使用copyreg
),序列化程序需要注册方法,使序列化程序能够创建所需类型的新对象,并将保存状态嵌入其中。为了使序列化程序不需要在加载时安装,序列化程序需要在pickle对象本身中包含所有必需的反序列化方法(这是可能的,因为pickle是递归的)
cloudpickle
假设安装了cloudpickle
,因此(为了使生成的pickle对象更小),不包括所有必需的方法。这与numpy
不同,作为反例,将方法转储到numpy.array
上,但在pickle中包含recostruct
方法(您可以将其视为numpy.core.multiarray\n\u recostruct
出现在数组的任何pickle中).您知道cloudpickle
是否可以进行递归,从而不需要安装它来取消pickle吗?或者答案是“它需要安装”。我是dill
的作者,所以我只能在理论上为cloudpickle
说话……然而,如果你想用forkingcloudpickle
来做这件事,我认为答案是“不”,至少不容易——你需要安装cloudpickle
。解决方法是,您需要使用copyreg
将cloudpickle
使用的每一个方法注册到pickle
中,然后还将生成的方法表(它是一个dict)保存为第一次打开的pickle(以便可以从globals
引用)在目标对象取消勾选之前。与此类似:
>>> import pickle
>>> new_squared = pickle.load(open('pickled_file', 'rb'))
>>> new_squared(2)
"ImportError: No module named cloudpickle.cloudpickle"