稳定的python序列化(例如,没有pickle模块重新定位问题)

稳定的python序列化(例如,没有pickle模块重新定位问题),python,serialization,pickle,Python,Serialization,Pickle,我正在考虑使用来定义一个数字及其单位。此值很可能必须存储在磁盘上。正如您可能知道的,pickle有一个主要问题:如果重新定位模块,取消pickle将无法解析类,也无法取消pickle信息。这种行为有一些变通方法,但它们确实是变通方法 对于这个问题,我设想的一个解决方案是创建一个对给定单元进行唯一编码的字符串。一旦您从磁盘获得此编码,您就将其传递给数量模块中的工厂方法,该方法将其解码到适当的单元实例。其优点是,即使重新定位模块,只要将魔术字符串标记传递给工厂方法,一切都将继续工作 这是一个已知的概

我正在考虑使用来定义一个数字及其单位。此值很可能必须存储在磁盘上。正如您可能知道的,pickle有一个主要问题:如果重新定位模块,取消pickle将无法解析类,也无法取消pickle信息。这种行为有一些变通方法,但它们确实是变通方法

对于这个问题,我设想的一个解决方案是创建一个对给定单元进行唯一编码的字符串。一旦您从磁盘获得此编码,您就将其传递给数量模块中的工厂方法,该方法将其解码到适当的单元实例。其优点是,即使重新定位模块,只要将魔术字符串标记传递给工厂方法,一切都将继续工作


这是一个已知的概念吗?

看起来像是惠勒第一条原则的应用,“计算机科学中的所有问题都可以通过另一个间接层次来解决”(第二条原则补充道,“但这通常会产生另一个问题”;-)。本质上,您需要做的是一个间接的方法来识别类型——类型中的实体可以使用类似pickle的方法(您可以研究
pickle.py
copy_reg.py
的源代码,了解后者的所有细节)

具体来说,我认为您要做的是子类
pickle.Pickler
并重写
save\u inst
方法。其中,当前版本说明:

    if self.bin:
        save(cls)
        for arg in args:
            save(arg)
        write(OBJ)
    else:
        for arg in args:
            save(arg)
        write(INST + cls.__module__ + '\n' + cls.__name__ + '\n')
您希望编写一些不同于类的模块和名称的东西——类的某种唯一标识符(由两个字符串组成),可能保存在您自己的一个或多个注册表中;对于
save\u global
方法也是如此

对于
Unpickler
的子类来说更容易,因为
\u实例化
部分已经在它自己的方法中被分解了:您只需要重写
find\u类
,即:

def find_class(self, module, name):
    # Subclasses may override this
    __import__(module)
    mod = sys.modules[module]
    klass = getattr(mod, name)
    return klass
它必须接受两个字符串并返回一个类对象;您可以通过您的注册表再次执行此操作

与涉及注册中心时一样,您需要考虑如何确保注册所有感兴趣的对象(类)等。这里的一个流行策略是不进行pickle,但确保所有类的移动、模块的重命名等都记录在永久的位置;这样,只有子类unpickler可以完成所有工作,并且它可以最方便地在重写的
find\u类中完成所有工作,绕过所有注册问题。我认为你认为这是一个“解决办法”,但对我来说,它似乎只是一个非常简单、有力和方便的实现“一个更高级别的间接”的概念,它避免了“一个更大的问题”;-)p>