pyyaml safe_load: 如何忽略本地标签

pyyaml safe_load: how to ignore local tags

我正在使用 yaml.safe_load() 但我需要忽略标签 !v2 -- 有没有办法做到这一点但仍然使用 safe_load()

我想通了,跟How can I add a python tuple to a YAML file using pyYAML?

有关

我只需要这样做:

  • 子类yaml.SafeLoader
  • 调用add_constructor!v2赋值给自定义构造方法
  • 在自定义构造方法中,做任何合适的事情
  • 使用yaml.load(..., MyLoaderClass)代替yaml.safe_load(...)

而且有效。

class V2Loader(yaml.SafeLoader):
    def let_v2_through(self, node):
        return self.construct_mapping(node)
V2Loader.add_constructor(
    u'!v2',
    V2Loader.let_v2_through)

   ....

y = yaml.load(info, Loader=V2Loader)

扩展现有答案以支持忽略所有未知标签。

import yaml

class SafeLoaderIgnoreUnknown(yaml.SafeLoader):
    def ignore_unknown(self, node):
        return None 

SafeLoaderIgnoreUnknown.add_constructor(None, SafeLoaderIgnoreUnknown.ignore_unknown)

root = yaml.load(content, Loader=SafeLoaderIgnoreUnknown)

的问题在于它仅适用于 v2 标签,并且仅当它所在的 yaml 对象是映射类型对象时才有效。

适用于所有标签,但问题是数据将被完全忽略。您只会得到一个 null 的数据。

如果您想忽略对所有标签的任何特殊处理,但仍然像标签不存在一样解析值,则以下方法应该有效:

def unknown(loader, suffix, node):
    if isinstance(node, yaml.ScalarNode):
        constructor = loader.__class__.construct_scalar
    elif isinstance(node, yaml.SequenceNode):
        constructor = loader.__class__.construct_sequence
    elif isinstance(node, yaml.MappingNode):
        constructor = loader.__class__.construct_mapping

    data = constructor(loader, node)

    return data

yaml.add_multi_constructor('!', unknown)
yaml.add_multi_constructor('tag:', unknown)

return yaml.load_all(infile, Loader=yaml.FullLoader)

请注意,如果您想使用不同的加载程序,例如 SafeLoader,您需要在调用加载函数之前明确向 add_multi_constructor() 提供加载程序:

yaml.add_multi_constructor('!', unknown, Loader=yaml.SafeLoader)

...

return yaml.load_all(infile, Loader=yaml.SafeLoader)