使用pyyaml / ruamel.yaml有条件地转储属性

问题描述

我有一个类似这样的Python类:

from dataclasses import dataclass
from ruamel.yaml import yaml_object,YAML

yaml = YAML()

@yaml_object(yaml)
@dataclass
class DataObject:
    normal_attr: str
    normal_attr_2: str
    conditional_attr: str

然后,我希望能够根据某些条件使用conditional_attr(基于PyYaml)有条件地转储ruamel.yaml。理想情况下,它将像这样工作:

data = DataObject()

if verbose_output:
    yaml.dump(data,stream)
else:
    yaml.dump(data,stream,exclude=['conditional_attr'])

当然这实际上不起作用,但是有什么方法可以实现这种行为?

解决方法

我认为实现排除某些映射键作为转储方法的选项不是一个好主意。

除了ruamel.yaml已经有一个 documented method to do special dumps,可用于过滤掉 任何属性,例如对于名称以conditional_开头的用户:

import sys
from dataclasses import dataclass
from ruamel.yaml import yaml_object,YAML

yaml = YAML()

verbose_output = False

@yaml_object(yaml)
@dataclass
class DataObject:
    normal_attr: str
    normal_attr_2: str
    conditional_attr: str

    @classmethod
    def to_yaml(cls,representer,node):
        d = {}
        for k in node.__annotations__:
            if not verbose_output and k.startswith('conditional_attr'):
                continue
            d[k] = node.__getattribute__(k)
        return representer.represent_mapping('!DataObject',d)

data = DataObject(normal_attr='a',normal_attr_2='b',conditional_attr='c')

yaml.dump(data,sys.stdout)

这给出了:

!DataObject
normal_attr: a
normal_attr_2: b