使用 Python 的 Pickle 加载时,如何将 module.Class() 替换为本地定义的 Class()?
Posted
技术标签:
【中文标题】使用 Python 的 Pickle 加载时,如何将 module.Class() 替换为本地定义的 Class()?【英文标题】:How to substitute module.Class() to locally defined Class() when loading with Python's Pickle? 【发布时间】:2011-03-05 15:09:44 【问题描述】:我有一个包含 foo.Bar() 对象数组的泡菜转储。我正在尝试取消腌制它,但 Bar() 类定义位于试图取消腌制的同一文件中,而不是在 foo 模块中。所以,pickle 抱怨它找不到模块 foo。
我尝试注入 foo 模块做类似的事情: 导入小鬼,系统
class Bar:
pass
foo_module = imp.new_module('foo')
foo_module.Bar = Bar
sys.modules['foo'] = foo_module
import foo
print foo.Bar()
哪个有效,但是当我尝试添加时,之后:
import pickle
p = pickle.load(open("my-pickle.pkl"))
我收到友好错误:
回溯(最近一次通话最后): 文件“pyppd.py”,第 69 行,在 ppds = 负载(ppds_decompressed) 文件“/usr/lib/python2.6/pickle.py”,第 1374 行,加载中 返回 Unpickler(file).load() 文件“/usr/lib/python2.6/pickle.py”,第 858 行,加载中 调度[键](自我) 文件“/usr/lib/python2.6/pickle.py”,第 1069 行,在 load_inst klass = self.find_class(模块,名称) 文件“/usr/lib/python2.6/pickle.py”,第 1124 行,在 find_class __import__(模块) 文件“/tmp/test.py”,第 69 行,在 p = pickle.load(open("my-pickle.pkl")) 文件“/usr/lib/python2.6/pickle.py”,第 1374 行,加载中 返回 Unpickler(file).load() 文件“/usr/lib/python2.6/pickle.py”,第 858 行,加载中 调度[键](自我) 文件“/usr/lib/python2.6/pickle.py”,第 1069 行,在 load_inst klass = self.find_class(模块,名称) 文件“/usr/lib/python2.6/pickle.py”,第 1124 行,在 find_class __import__(模块) ImportError:没有名为 foo 的模块有什么想法吗?
【问题讨论】:
【参考方案1】:class Bar:
pass
class MyUnpickler(pickle.Unpickler):
def find_class(self, module, name):
if module == "foo" and name == "Bar":
return Bar
else:
return pickle.Unpickler.find_class(self, module, name)
bars = MyUnpickler(open("objects.pkl")).load()
注意事项注意事项:
如果您从另一个模块调用这个 sn-p 代码,比如说 baz
,那么未腌制的对象将是 baz.Bar
类型,而不是 foo.Bar
。假设foo.Bar
和baz.Bar
的类定义是一样的,你就可以轻松解压了。但是要小心下游使用isinstance
、type
等。一般来说,尝试为任何事情做这种事情而不是一次性的可能并不聪明,因为你的代码库现在包含Bar
的两个实例.如果可能的话,你应该把 foo
放在你的 PATH 中。
【讨论】:
谢谢,这就像一个魅力。无论如何,我会更加努力地考虑是否可以避免这样做...... 更一般地说,您可以编写if module == "foo": return getattr(sys.modules[__name__], name)
,这样相同的代码将适用于同一模块中本地定义的所有类,而不仅仅是Bar
。以上是关于使用 Python 的 Pickle 加载时,如何将 module.Class() 替换为本地定义的 Class()?的主要内容,如果未能解决你的问题,请参考以下文章
TypeError:需要一个类似字节的对象,而不是使用 pickle 加载时的“str”
如何在小 GUI 中修复“allow_pickle=False 时无法加载对象数组”