在Python 2中从Python 3中取消选择类

Cas*_*ash 6 python pickle python-3.x

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

假设我们有如下代码.

寄件人

pickle.dumps(obj,2)
Run Code Online (Sandbox Code Playgroud)

接收器

pickle.loads(atom)
Run Code Online (Sandbox Code Playgroud)

给出具体案例,如果obj={},则给出的错误是:

ImportError:没有名为builtins的模块

这是因为Python 2使用了__builtin__.

问题是解决此问题的最佳方法.

Cas*_*ash 14

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

如果我们导入:

from lib2to3.fixes.fix_imports import MAPPING
Run Code Online (Sandbox Code Playgroud)

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

REVERSE_MAPPING={}
for key,val in MAPPING.items():
    REVERSE_MAPPING[val]=key
Run Code Online (Sandbox Code Playgroud)

我们可以覆盖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()  
Run Code Online (Sandbox Code Playgroud)

然后我们调用此加载而不是pickle.loads.

这应该可以解决问题.