如果使用协议2对Python 3类进行pickle,它应该在Python 2中工作,但不幸的是,这会失败,因为某些类的名称已经改变。
假设我们的代码如下所示。
发件人
pickle.dumps(obj,2)
接收机
pickle.loads(atom)
要给出具体案例,如果obj={}
,则给出的错误是:
ImportError:没有名为builtins的模块
这是因为Python 2改为使用__builtin__
。
问题是解决此问题的最佳方法。
答案 0 :(得分:14)
此问题为Python issue 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。
这应该可以解决问题。