gpt4 book ai didi

python - Python 中优雅降级的 pickle

转载 作者:太空狗 更新时间:2023-10-30 00:12:20 24 4
gpt4 key购买 nike

(您可以阅读 this 问题了解一些背景)

我希望有一种优雅降级的方式来在 Python 中 pickle 对象。

当 pickle 一个对象时,我们称它为主对象,有时 Pickler 会抛出一个异常,因为它不能 pickle 主对象的某个子对象。例如,我经常遇到的一个错误是“无法 pickle 模块对象”。那是因为我从主对象引用了一个模块。

我知道我可以写一些东西来用包含模块属性的外观替换该模块,但这会有自己的问题 (1)。

所以我想要的是一个 pickling 函数,它可以自动用包含其属性的外观替换模块(以及任何其他难以 pickle 的对象)。这可能不会产生完美的 pickle ,但在许多情况下就足够了。

有这样的吗?有谁知道如何处理这个问题?


(1) 一个问题是该模块可能正在引用其中的其他模块。

最佳答案

您可以决定并实现任何以前不可 pickle 的类型如何被 pickled 和 unpickled:参见标准库模块 copy_reg (在 Python 3.* 中重命名为 copyreg)。

本质上,您需要提供一个函数,该函数在给定类型实例的情况下将其缩减为一个元组——使用与 reduce 相同的协议(protocol)。特殊方法(除了 reduce 特殊方法不接受任何参数,因为当提供时直接在对象上调用它,而您提供的函数将把对象作为唯一参数)。

通常,您返回的元组有 2 个项目:一个可调用对象和一个要传递给它的参数元组。可调用对象必须注册为“安全构造函数”或等效地具有具有真值的属性 __safe_for_unpickling__。这些项目将被 pickle ,在取消 pickle 时,将使用给定的参数调用可调用对象,并且必须返回未挑选的对象。

例如,假设您只想按名称 pickle 模块,这样取消 pickle 就意味着重新导入它们(即为了简单起见,假设您不关心动态修改的模块、嵌套包等,只是简单的顶层模块)。然后:

>>> import sys, pickle, copy_reg
>>> def savemodule(module):
... return __import__, (module.__name__,)
...
>>> copy_reg.pickle(type(sys), savemodule)
>>> s = pickle.dumps(sys)
>>> s
"c__builtin__\n__import__\np0\n(S'sys'\np1\ntp2\nRp3\n."
>>> z = pickle.loads(s)
>>> z
<module 'sys' (built-in)>

我使用老式的 ASCII 形式的 pickle,这样包含 pickle 的字符串 s 很容易检查:它指示 unpickling 调用内置导入函数,使用字符串 sys 作为它的唯一参数。 z 表明,这确实如我们所愿地返回了内置的 sys 模块作为 unpickling 的结果。

现在,您必须使事情变得比 __import__ 更复杂一些(您将不得不处理保存和恢复动态更改、导航嵌套 namespace 等),因此您还必须调用 copy_reg.constructor(将执行此工作的您自己的函数作为参数传递),然后再调用 copy_reg 返回其他函数的模块保存函数(并且,如果在单独的运行中,也在你解开你使用所述功能制作的 pickle 之前)。但我希望这些简单的案例有助于表明它实际上并没有什么“本质上”复杂的东西!-)

关于python - Python 中优雅降级的 pickle ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1348315/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com