6

如果使用协议 2 腌制 Python 3 类,它应该在 Python 2 中工作,但不幸的是,这会失败,因为某些类的名称已更改。

假设我们有如下调用的代码。

发件人

pickle.dumps(obj,2)

接收者

pickle.loads(atom)

给出一个特定的情况,如果obj={},那么给出的错误是:

ImportError:没有名为 builtins 的模块

这是因为 Python 2__builtin__改为使用。

这个问题是解决这个问题的最好方法。

4

1 回答 1

14

这个问题是Python 问题 3675 ​​。这个错误实际上已在 Python 3.11 中修复。

如果我们导入:

from lib2to3.fixes.fix_imports import MAPPING

MAPPING 将 Python 2 名称映射到 Python 3 名称。我们想要反过来。

REVERSE_MAPPING={}
for key,val in MAPPING.items():
    REVERSE_MAPPING[val]=key

我们可以覆盖 Unpickler 并加载

class Python_3_Unpickler(pickle.Unpickler):
    """Class for pickling objects from Python 3"""
    def find_class(self,module,name):
        if module in REVERSE_MAPPING:
            module=REVERSE_MAPPING[module]
        __import__(module)
        mod = sys.modules[module]
        klass = getattr(mod, name)
        return klass

def loads(str):
    file = pickle.StringIO(str)
    return Python_3_Unpickler(file).load()  

然后我们将其称为负载而不是 pickle.loads。

这应该可以解决问题。

于 2009-09-06T07:18:45.133 回答