在PyYAML中访问当前节点的键/名称

时间:2018-04-10 14:40:02

标签: python pyyaml

我使用自定义YAML标记将YAML文件反序列化为Python对象。像这样:

MyList:
  Object1: !MyObject
    value1: Test
    value2: 1.0

通过class_method from_yaml我调用MyObject __init__方法,并将loader.construct_mapping提供的所有字段发送给它。

@classmethod
def from_yaml(cls, loader, node):
  fields = loader.construct_mapping(node, deep = True)
  return cls(**fields)

所有已配置的字段都以__init__ MyObject方式传递给MyObject。全部,但只有一个:所描述的Object1实例的实际名称,即字符串name == "Object1"

如何获取实例的名称以便执行def __init__(self, name, **fields): self.name = name for attr in fields: val = fields[attr] setattr(self, attr, val)

之类的操作
scale

1 个答案:

答案 0 :(得分:0)

您的YAML中有一个键Object1和一个带有标记!MyObject的标记映射的值。对于YAML,该键不是实例的名称,它只是映射中的一个键,其值恰好是标记映射。

构建标记的映射该密钥不可用时,因为它不是您对象的一部分。解析器当然已经将那个键Object1构建在某个节点作为节点,当它开始解析你的对象时,但是你不能在不大量改变解析器的情况下访问它。如果你这样做,如果你的YAML看起来像事情可能会破坏:

MyList:
  - !MyObject
    value1: Test
    value2: 1.0

没有这样的钥匙。

IMO你应该改变你的YAML看起来像:

MyList: !MyObject
  Object1:
    value1: Test
    value2: 1.0

或者对于以下内容,这更容易加载:

MyList:
  - !MyObject
    name: Object1
    value1: Test
    value2: 1.0

如果您无法更改YAML,最好的选择是编写一个(递归)树木漫步者,在您致电safe_load()后更新您的对象。

您还应该考虑将from_yaml写为生成器。就像现在一样,只要你的!MyObject获得更复杂的值,可能会在未来某个时候包含自我引用,就会中断。