您可以决定和实现任何以前不可提取的类型如何被腌制和取消腌制:请参阅标准库模块 copy_reg(在 Python 3.* 中重命名为 copyreg)。
本质上,您需要提供一个函数,在给定类型实例的情况下,将其简化为元组——使用与 reduce 特殊方法相同的协议(除了 reduce 特殊方法不带参数,因为提供时直接在对象上调用,而您提供的函数将对象作为唯一参数)。
通常,您返回的元组有 2 项:一个可调用项和一个要传递给它的参数元组。可调用对象必须注册为“安全构造函数”或等效地具有属性__safe_for_unpickling__ 和真值。这些项目将被腌制,并且在取消腌制时,将使用给定的参数调用可调用对象,并且必须返回未选中的对象。
例如,假设您只想按名称腌制模块,因此取消腌制它们只是意味着重新导入它们(即,为简单起见,假设您不关心动态修改的模块、嵌套包等,只是简单顶级模块)。那么:
>>> 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__ 更复杂一些(您必须处理保存和恢复动态更改、导航嵌套命名空间等),因此您必须在你之前调用copy_reg.constructor(作为参数传递你自己的函数来执行这项工作)copy_reg返回你的其他函数的模块保存函数(并且,如果在单独的运行中,也在你解开那些你使用的泡菜之前说函数)。但我希望这个简单的案例有助于表明,实际上并没有什么“本质上”复杂的!-)