在Python 2中反序列化Python 3的类
如果用协议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。
这样应该就能解决这个问题了。