在Python 2中反序列化Python 3的类

6 投票
1 回答
1951 浏览
提问于 2025-04-15 14:06

如果用协议2把一个Python 3的类进行序列化(也就是“打包”),理论上它应该可以在Python 2中使用,但实际上会出问题,因为某些类的名字发生了变化。

假设我们有以下代码。

发送者

pickle.dumps(obj,2)

接收者

pickle.loads(atom)

举个具体的例子,如果obj={},那么会出现这样的错误:

ImportError: No module named builtins

这是因为Python 2使用的是__builtin__,而不是“builtins”。

问题是,解决这个问题的最佳方法是什么。

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 和 loads。

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()  

然后我们调用这个 loads,而不是 pickle.loads。

这样应该就能解决这个问题了。

撰写回答