在ruamel from_yaml

如何解决在ruamel from_yaml

我正在创建一个自定义的Yaml标签mytag。它可以包含任何给定的有效Yaml-映射,标量,锚点,序列等。

我如何实现mytag类来对该标签建模,以使ruamel解析!mytag内容与解析任何给定的Yaml完全相同? mytag实例仅存储yaml内容的任何解析结果。

以下代码有效,并且断言应确切说明应该应该执行的操作,并且都可以通过。

但是我不确定它是否由于正确的原因而工作。 。 。特别是在from_yaml方法中,是否建议使用commented_obj = constructor.construct_undefined(node)来实现这一点,并且消耗了1个生成器中只有1个正确吗?这不是偶然的吗?

我应该改construct_object还是construct_map或。 。 。?我能够找到的示例倾向于知道其构造的类型,因此可以使用construct_mapconstruct_sequence来选择构造哪种类型的对象。在这种情况下,我实际上想将常规/标准ruamel解析带回去,以了解其中可能存在的未知类型,然后将其存储为自己的类型。

import ruamel.yaml
from ruamel.yaml.comments import CommentedMap,CommentedSeq,TaggedScalar


class mytag():
    yaml_tag = '!mytag'

    def __init__(self,value):
        self.value = value

    @classmethod
    def from_yaml(cls,constructor,node):
        commented_obj = constructor.construct_undefined(node)
        flag = False
        for data in commented_obj:
            if flag:
                raise AssertionError('should only be 1 thing in generator??')
            flag = True

        return cls(data)


with open('mytag-sample.yaml') as yaml_file:
    yaml_parser = ruamel.yaml.YAML()
    yaml_parser.register_class(mytag)
    yaml = yaml_parser.load(yaml_file)

custom_tag_with_list = yaml['root'][0]['arb']['k2']
assert type(custom_tag_with_list) is mytag
assert type(custom_tag_with_list.value) is CommentedSeq
print(custom_tag_with_list.value)

standard_list = yaml['root'][0]['arb']['k3']
assert type(standard_list) is CommentedSeq
assert standard_list == custom_tag_with_list.value

custom_tag_with_map = yaml['root'][1]['arb']
assert type(custom_tag_with_map) is mytag
assert type(custom_tag_with_map.value) is CommentedMap
print(custom_tag_with_map.value)

standard_map = yaml['root'][1]['arb_no_tag']
assert type(standard_map) is CommentedMap
assert standard_map == custom_tag_with_map.value

custom_tag_scalar = yaml['root'][2]
assert type(custom_tag_scalar) is mytag
assert type(custom_tag_scalar.value) is TaggedScalar

standard_tag_scalar = yaml['root'][3]
assert type(standard_tag_scalar) is str
assert standard_tag_scalar == str(custom_tag_scalar.value)

还有一些样本yaml:

root:
  - item: blah
    arb:
      k1: v1
      k2: !mytag
        - one
        - two
        - three-k1: three-v1
          three-k2: three-v2
          three-k3: 123 # arb comment
          three-k4: 
            - a
            - b
            - True
      k3:
        - one
        - two
        - three-k1: three-v1
          three-k2: three-v2
          three-k3: 123 # arb comment
          three-k4: 
            - a
            - b
            - True
  - item: argh
    arb: !mytag
            k1: v1
            k2: 123
            # blah line 1
            # blah line 2
            k3:
              k31: v31
              k32: 
                - False
                - string here
                - 321
    arb_no_tag:
      k1: v1
      k2: 123
      # blah line 1
      # blah line 2
      k3:
        k31: v31
        k32: 
          - False
          - string here
          - 321
  - !mytag plain scalar
  - plain scalar
  - item: no comment
    arb:
      - one1
      - two2

解决方法

在YAML中,您可以具有锚点和别名,并且让对象成为其自身的子对象(使用别名)是完全可以的。如果要转储Python数据结构data

data = [1,2,4,dict(a=42)]
data[3]['b'] = data

它转储到:

&id001
- 1
- 2
- 4
- a: 42
  b: *id001

,为此,锚和别名是必需的。

在加载这样的结构时,ruamel.yaml会递归到嵌套的数据结构中,但是如果顶级节点尚未导致要构造可作为锚点引用的实际对象,则递归叶无法解析别名

为解决这个问题,除了标量值外,使用了一个生成器。它首先创建一个空对象,然后递归并更新其值。在调用构造函数的代码中,进行检查以查看是否返回了生成器,在这种情况下,对数据执行了next(),并潜在地实现了“递归”自递归。

由于您调用construct_undefined(),所以总会得到一个生成器。实际上,如果该方法检测到标量节点(当然不能递归),则可能会返回值,但不会。如果可以,您的代码将无法加载以下YAML文档:

!mytag 1

无需修改即可测试您是否生成了生成器,就像ruamel.yaml中的代码调用了各种构造函数那样,以便它可以处理construct_undefined和e.g. construct_yaml_int(不是生成器)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?