代码之家  ›  专栏  ›  技术社区  ›  Casebash

从python 2中的python 3解压类

  •  6
  • Casebash  · 技术社区  · 15 年前

    如果使用协议2对python 3类进行pickle处理,那么它应该在python 2中工作,但不幸的是,这失败了,因为某些类的名称已经更改。

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

    发件人

    pickle.dumps(obj,2)
    

    接收机

    pickle.loads(atom)
    

    如果 obj={} ,则给出的错误为:

    导入错误:没有名为builtins的模块

    这是因为python 2使用 __builtin__ 相反。

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

    1 回复  |  直到 13 年前
        1
  •  14
  •   Casebash    15 年前

    这个问题是 Python issue 3675 . 这个bug实际上是在Python3.11中修复的。

    如果我们进口:

    from lib2to3.fixes.fix_imports import 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()  
    

    然后我们将此负载称为pickle.loads。

    这样可以解决问题。