gpt4 book ai didi

python - 如何处理 PyYaml 中的标签/类向后兼容性?

转载 作者:太空宇宙 更新时间:2023-11-03 20:39:47 24 4
gpt4 key购买 nike

假设我有一个类 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 从不调用此自定义加载。还有其他方法可以将旧标签注入(inject)到加载过程中吗?

最佳答案

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

看起来 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)

关于python - 如何处理 PyYaml 中的标签/类向后兼容性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56932354/

24 4 0