【问题标题】:How to properly set up YAML flow style dumping using round-trip with ruamel.yaml?如何使用 ruamel.yaml 往返正确设置 YAML 流样式转储?
【发布时间】:2020-11-24 18:13:09
【问题描述】:

我正在使用 ruamel.yaml 包,我似乎无法让它以格式良好的流样式输出。我想通过尾随逗号和换行符将元素保持在同一级别。我也想保留每一条评论,转换为流式风格后似乎有些消失了。这是一个例子:

原创

background_opacity: 0.9 # comment
cursor: {style: Beam}

# comment
font:
    normal: {family: Fira Code, style: Retina} # comment
    size: 12.0 # comment

打算

{
    background_opacity: 0.9, # comment
    cursor: {style: Beam},
    
    # comment
    font: {
        normal: {family: Fira Code, style: Retina}, # comment
        size: 12.0 # comment
    }
}

实际

{background_opacity: 0.9 # comment
, cursor: {style: Beam}, font: {normal: {family: Fira Code, style: Retina} # comment
, size: 12.0   # comment
}}

我的代码附在下面。我对 YAML 和 ruamel.yaml 还很陌生,所以对于任何简单的错误,我深表歉意。

from ruamel.yaml import YAML

def round_trip(sout, sin, idt):
    yaml = YAML()
    assert idt >= 2
    yaml.indent(mapping=idt, sequence=idt, offset=idt-2)
    yaml.preserve_quotes = True

    data = yaml.load(sin)
    if data is not None:
        data.fa.set_flow_style() # needs fixing: commas are not trailing
        yaml.dump(data, sout)
    else:
        print("the file is empty") # needs fixing: should dump original file

【问题讨论】:

    标签: python yaml ruamel.yaml


    【解决方案1】:

    您似乎没有做错任何事情,但是 ruamel.yaml 不支持进行那种输出。它只是试图在一行中填充尽可能多的流样式,而你得到换行符是因为输出 cmets(与它们之前的映射键相关联,会强制换行。

    如果您的输入没有任何 cmets,那么您最终会得到一两行,具体取决于您设置的输出宽度。

    如果您在加载时为每一行附加一个虚拟注释,并在转储后将其删除,您可能会得到更好的结果,但这仍然不会让您在自己的一行上打开大括号。

    目前您只设置了根级别样式属性,因为您没有嵌套的块样式集合,所以该属性“有效”。您应该使用以下方法递归地执行此操作:

    def set_style(d, flow):
        if isinstance(d, dict):
            if flow:
                d.fa.set_flow_style()
            else:
                d.fa.set_block_style()
            for k in d:
                set_style(d[k], flow)
        elif isinstance(d, list):
            if flow:
                d.fa.set_flow_style()
            else:
                d.fa.set_block_style()
            for item in d:
                 set_style(item, flow)
    
    
    data = yaml.load(sin)
    set_style(data, flow=True)
    

    【讨论】:

    • 我明白了。另一方面,有没有办法从流式风格转变为“纯”块式风格?如果我想删除所有大括号并将其替换为块样式缩进,ruamel.yaml 是否支持?我试过fa.set_block_style(),但保留了一些大括号。
    • 您是否对所有字典和列表递归地执行了fa.set_block_style()?该方法仅设置您调用它的元素的样式,在您的示例中以非递归方式工作,因为它仅在数据结构的根部具有块样式。通常,剩下的唯一流式花括号/方括号应该用于空字典。列表。
    • 我不相信我做到了,哎呀。我以非递归方式调用fa.set_block_style(),就像我为流样式所做的那样。有没有简单/推荐的编码方式?
    • 对于set_style(d[k], flow) 和set_style(d[item], flow) 行,我收到错误TypeError: list indices must be integers or slices, not ScalarFloat。对不起,我也是 Python 新手,你能帮我解决这个问题吗?我将d[k] 更改为仅d 和d[item] 更改为item,因为我想遍历这些结构并且它似乎有效,但我不确定输出是否是预期的。这是一个适当的修复吗?
    • 我无法再编辑我上面的评论,但我不相信我的改变是正确的——我认为它改变了列表/字典的副本,所以原始的不会被改变。我应该如何以可以编辑的方式引用子元素?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-21
    • 2021-06-03
    • 1970-01-01
    • 2020-05-30
    • 2021-08-30
    • 2018-03-30
    • 2019-04-01
    相关资源
    最近更新 更多