【问题标题】:How to handle tag/class backwards-compatibility in PyYaml?如何在 PyYaml 中处理标签/类的向后兼容性?
【发布时间】:2019-11-17 19:36:53
【问题描述】:

假设我有一个类MyClass 驻留在包my_package 中。将此类数据转储到 YAML 可能会产生:

!!python/object:my_package.MyClass
my_field_1: "foo"
my_field_2: "bar"

这个数据可以用默认的加载器反序列化就好了。但是我们如何处理重构包/类名呢?例如,如果我们将包重命名为 my_new_package,代码无法像预期的那样反序列化现有的 YAML 文件:

yaml.constructor.ConstructorError: while constructing a Python object
cannot find 'MyClass' in the module 'my_package'

如何向 YAML 加载器添加向后兼容性,以便仍然可以加载旧数据?


我的第一次尝试是自定义加载器并注册旧标签名称以实现向后兼容性:

class CustomLoader(yaml.SafeLoader):
    pass

def my_class_loader(loader, node):
    # to be implemented

CustomLoader.add_constructor("!!python/object:my_package.MyClass", my_class_loader)

data = yaml.load(f, Loader=CustomLoader)

不幸的是,PyYaml 从未调用此自定义加载。有没有其他方法可以将旧标签注入到加载过程中?

【问题讨论】:

    标签: python pyyaml


    【解决方案1】:

    我找到了一个可行的解决方案,但我不确定这是否是最优雅的解决方法:

    看起来 PyYaml 在执行构造函数查找之前在内部将存储的标签 !!python/object:my_package.MyClass 转换为 tag:yaml.org,2002:python/object:my_package.MyClass。

    因此,为了为旧标签名称注册一个自定义加载器,可以执行以下操作:

    # Example class
    class MyClass(object):
        def __init__(my_field_1, my_field_2):
            self.my_field_1 = my_field_1
            self.my_field_2 = my_field_2
    
        @staticmethod
        def from_dict(d):
            return MyClass(
                my_field_1=d["my_field_1"],
                my_field_2=d["my_field_2"],
            )
    
    # Build a custom loader
    class CustomLoader(yaml.SafeLoader):
        pass
    
    def my_class_loader(loader, node):
        mapping = loader.construct_mapping(node)
        return MyClass.from_dict(mapping)
    
    # Register the old tag name
    CustomLoader.add_constructor(
        "tag:yaml.org,2002:python/object:my_package.MyClass", 
        my_class_loader)
    
    # Load using custom loader
    data = yaml.load(f, Loader=CustomLoader)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-18
      • 1970-01-01
      • 1970-01-01
      • 2015-11-25
      • 2021-08-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多