关于import:如何在使用Python的Pickle加载时将module.Class()替换为本地定义的Class()?

How to substitute module.Class() to locally defined Class() when loading with Python's Pickle?

我有一个pickle转储,它有一个foo.bar()对象数组。我正试图取消拾取它,但是bar()类定义与尝试取消拾取的文件相同,而不是在foo模块中。所以,pickle抱怨它找不到foo模块。

我尝试注入foo模块,做类似的事情:导入IMP

1
2
3
4
5
6
7
8
9
class Bar:
    pass

foo_module = imp.new_module('foo')
foo_module.Bar = Bar
sys.modules['foo'] = foo_module

import foo
print foo.Bar()

这是可行的,但当我尝试添加时,在这之后:

1
2
import pickle
p = pickle.load(open("my-pickle.pkl"))

我收到友好错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Traceback (most recent call last):
  File"pyppd.py", line 69, in
    ppds = loads(ppds_decompressed)
  File"/usr/lib/python2.6/pickle.py", line 1374, in loads
    return Unpickler(file).load()
  File"/usr/lib/python2.6/pickle.py", line 858, in load
    dispatch[key](self)
  File"/usr/lib/python2.6/pickle.py", line 1069, in load_inst
    klass = self.find_class(module, name)
  File"/usr/lib/python2.6/pickle.py", line 1124, in find_class
    __import__(module)
  File"/tmp/test.py", line 69, in
    p = pickle.load(open("my-pickle.pkl"))
  File"/usr/lib/python2.6/pickle.py", line 1374, in loads
    return Unpickler(file).load()
  File"/usr/lib/python2.6/pickle.py", line 858, in load
    dispatch[key](self)
  File"/usr/lib/python2.6/pickle.py", line 1069, in load_inst
    klass = self.find_class(module, name)
  File"/usr/lib/python2.6/pickle.py", line 1124, in find_class
    __import__(module)
ImportError: No module named foo

有什么想法吗?


1
2
3
4
5
6
7
8
9
10
11
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()

警告警告警告:如果您从另一个模块调用这段代码,比如说baz,那么未选中的对象将是baz.Bar类型,而不是foo.Bar类型。假设foo.Barbaz.Bar的类定义是相同的,您就可以轻松地取消拾取了。但是在下游使用isinstancetype等时要小心。一般来说,试图一次性完成这类工作可能不明智,因为您的代码库现在包含两个Bar实例。如果可能的话,你应该把foo放在你的道路上。