在没有安装 cloudpickle 的情况下解开 cloudpickle
Unpickle a cloudpickle without cloudpickle installation
Python 标准库中的默认 pickle
模块不允许使用闭包、lambda 或 __main__
中的函数序列化函数(参见 here ).
我需要使用一些自定义函数来 pickle 一个对象,这些函数在将被取消 pickle 的地方将无法导入。还有一些其他 Python 对象序列化程序,包括 dill
和 cloudpickle
,它们能够执行此操作。
cloudpickle
documentation 似乎在说,即使你使用 cloudpickle
进行 pickle,你也可以使用标准 pickle
模块进行 unpickle。这非常有吸引力,因为我什至无法在需要解包的环境中安装包。
确实,文档中的示例基本上执行以下操作:
泡菜:
>>> import cloudpickle
>>> squared = lambda x: x ** 2
>>> pickled_lambda = cloudpickle.dump(squared, open('pickled_file', 'w'))
拆开:
>>> import pickle
>>> new_squared = pickle.load(open('pickled_file', 'rb'))
>>> new_squared(2)
但是,运行在未安装 cloudpickle
的环境中使用第二个块,即使它从未导入,也会产生错误:
"ImportError: No module named cloudpickle.cloudpickle"
可能最容易重现的例子是为 Python2 安装 cloudpickle
,第一个块 运行,然后尝试用第二个块加载 pickled 文件使用 Python3(未安装 cloudpickle
)。
这是怎么回事?为什么 cloudpickle
需要安装到 运行 标准 pickle
负载,如果它甚至没有被调用?
理论上,cloudpickle
不需要安装到 load
腌制对象。从理论上讲,cloudpickle
所做的也将包括所有必要的函数,以便在该对象中取消选中该对象。不过,那是理论上的。
在方法注册表中(例如使用 copyreg
),序列化程序需要注册使序列化程序能够创建所需类型的新对象并将其注入已保存状态的方法。对于不需要在加载时安装的序列化程序,序列化程序需要在 pickle 对象本身中包含所有必需的反序列化方法(这是可能的,因为 pickle 是递归的)。
cloudpickle
假定安装了 cloudpickle
,因此(为了使生成的腌制对象更小),不包括所有必需的方法。这与 numpy
不同,作为反例,numpy.array
上的 dumps
方法确实包含 pickle 中的 reconstruct
方法(您可以将其视为 numpy.core.multiarray\n_reconstruct
出现在 array
) 的任何 pickle 中。
Python 标准库中的默认 pickle
模块不允许使用闭包、lambda 或 __main__
中的函数序列化函数(参见 here ).
我需要使用一些自定义函数来 pickle 一个对象,这些函数在将被取消 pickle 的地方将无法导入。还有一些其他 Python 对象序列化程序,包括 dill
和 cloudpickle
,它们能够执行此操作。
cloudpickle
documentation 似乎在说,即使你使用 cloudpickle
进行 pickle,你也可以使用标准 pickle
模块进行 unpickle。这非常有吸引力,因为我什至无法在需要解包的环境中安装包。
确实,文档中的示例基本上执行以下操作:
泡菜:
>>> import cloudpickle
>>> squared = lambda x: x ** 2
>>> pickled_lambda = cloudpickle.dump(squared, open('pickled_file', 'w'))
拆开:
>>> import pickle
>>> new_squared = pickle.load(open('pickled_file', 'rb'))
>>> new_squared(2)
但是,运行在未安装 cloudpickle
的环境中使用第二个块,即使它从未导入,也会产生错误:
"ImportError: No module named cloudpickle.cloudpickle"
可能最容易重现的例子是为 Python2 安装 cloudpickle
,第一个块 运行,然后尝试用第二个块加载 pickled 文件使用 Python3(未安装 cloudpickle
)。
这是怎么回事?为什么 cloudpickle
需要安装到 运行 标准 pickle
负载,如果它甚至没有被调用?
理论上,cloudpickle
不需要安装到 load
腌制对象。从理论上讲,cloudpickle
所做的也将包括所有必要的函数,以便在该对象中取消选中该对象。不过,那是理论上的。
在方法注册表中(例如使用 copyreg
),序列化程序需要注册使序列化程序能够创建所需类型的新对象并将其注入已保存状态的方法。对于不需要在加载时安装的序列化程序,序列化程序需要在 pickle 对象本身中包含所有必需的反序列化方法(这是可能的,因为 pickle 是递归的)。
cloudpickle
假定安装了 cloudpickle
,因此(为了使生成的腌制对象更小),不包括所有必需的方法。这与 numpy
不同,作为反例,numpy.array
上的 dumps
方法确实包含 pickle 中的 reconstruct
方法(您可以将其视为 numpy.core.multiarray\n_reconstruct
出现在 array
) 的任何 pickle 中。