使用没有引号

时间:2018-05-24 23:18:54

标签: python yaml

如何使用PyYAML加载和转储YAML,以便尽可能使用原始样式?

我有Python加载和转储YAML数据,如:

import sys
import yaml

def _represent_dictorder(self, data):
    # Maintains ordering of specific dictionary keys in the YAML output.
    _data = []
    ordering = ['questions', 'tags', 'answers', 'weight', 'date', 'text']
    for key in ordering:
        if key in data:
            _data.append((str(key), data.pop(key)))
    if data:
        _data.extend(data.items())
    return self.represent_mapping(u'tag:yaml.org,2002:map', _data)

yaml.add_representer(dict, _represent_dictorder)

text="""-   questions:
    -   Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    tags:
        context: curabitur
    answers:
    -   weight: 2
        date: 2014-1-19
        text: |-
            1. Mauris lorem magna, auctor et tristique id, fringilla ut metus.
            2. Donec pellentesque elit non felis feugiat, in gravida ex hendrerit.
            3. Mauris quis velit sapien. Nullam blandit, diam et pharetra maximus, mi erat scelerisque turpis, eu vestibulum dui ligula non lectus.
                a. Aenean consectetur eleifend accumsan.
            4. In erat lacus, egestas ut tincidunt ac, congue quis elit. Suspendisse semper purus ac turpis maximus dignissim.
                a. Proin nec neque convallis, placerat odio non, suscipit erat. Nulla nec mattis nibh, accumsan feugiat felis.
            5. Mauris lorem magna, auctor et tristique id, fringilla ut metus.
                a. Morbi non arcu odio. Maecenas faucibus urna et leo euismod placerat.
                b. Nulla facilisi. Pellentesque at pretium nunc.
                c. Ut ipsum nibh, suscipit a pretium eu, eleifend vitae purus.
"""
yaml.dump(yaml.load(text), stream=sys.stdout, default_flow_style=False, indent=4)

但是这会以不同的方式输出YAML,例如:

-   questions:
    - Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    tags:
        context: curabitur
    answers:
    -   weight: 2
        date: 2014-1-19
        text: "1. Mauris lorem magna, auctor et tristique id, fringilla ut metus.\n\
            2. Donec pellentesque elit non felis feugiat, in gravida ex hendrerit.\n\
            3. Mauris quis velit sapien. Nullam blandit, diam et pharetra maximus,\
            \ mi erat scelerisque turpis, eu vestibulum dui ligula non lectus.\n \
            \   a. Aenean consectetur eleifend accumsan.\n4. In erat lacus, egestas\
            \ ut tincidunt ac, congue quis elit. Suspendisse semper purus ac turpis\
            \ maximus dignissim.\n    a. Proin nec neque convallis, placerat odio\
            \ non, suscipit erat. Nulla nec mattis nibh, accumsan feugiat felis.\n\
            5. Mauris lorem magna, auctor et tristique id, fringilla ut metus.\n \
            \   a. Morbi non arcu odio. Maecenas faucibus urna et leo euismod placerat.\n\
            \    b. Nulla facilisi. Pellentesque at pretium nunc.\n    c. Ut ipsum\
            \ nibh, suscipit a pretium eu, eleifend vitae purus."

正如您所看到的,它正在改变文本块的样式,因此新行被转义,使得阅读更加困难。

所以我尝试指定default_style属性,如:

yaml.dump(yaml.load(text), stream=sys.stdout, default_flow_style=False, default_style='|', indent=4)

这修复了文本块样式,但是它通过在所有其他字符串周围加上引号,向单行字符串添加换行符以及修改整数来打破其他样式,例如:

-   "questions":
    - |-
        Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    "tags":
        "context": |-
            curabitur
    "answers":
    -   "weight": !!int |-
            2
        "date": |-
            2014-1-19
        "text": |-
            1. Mauris lorem magna, auctor et tristique id, fringilla ut metus.
            2. Donec pellentesque elit non felis feugiat, in gravida ex hendrerit.
            3. Mauris quis velit sapien. Nullam blandit, diam et pharetra maximus, mi erat scelerisque turpis, eu vestibulum dui ligula non lectus.
                a. Aenean consectetur eleifend accumsan.
            4. In erat lacus, egestas ut tincidunt ac, congue quis elit. Suspendisse semper purus ac turpis maximus dignissim.
                a. Proin nec neque convallis, placerat odio non, suscipit erat. Nulla nec mattis nibh, accumsan feugiat felis.
            5. Mauris lorem magna, auctor et tristique id, fringilla ut metus.
                a. Morbi non arcu odio. Maecenas faucibus urna et leo euismod placerat.
                b. Nulla facilisi. Pellentesque at pretium nunc.
                c. Ut ipsum nibh, suscipit a pretium eu, eleifend vitae purus.

如何解决此问题,以便输出类似于原始输入的样式?

1 个答案:

答案 0 :(得分:1)

您如何确定哪个字符串表示为块文字(或者说是折叠块)以及内联代表什么?

假设您只想要使用跨越多行的字符串的块文字,您可以编写自己的字符串表示符,以根据字符串内容在样式之间切换:

def selective_representer(dumper, data):
    return dumper.represent_scalar(u"tag:yaml.org,2002:str", data,
                                   style="|" if "\n" in data else None)

yaml.add_representer(str, selective_representer)

现在,如果您将默认流式样设置为False转储数据(以防止dict / list内联):

yaml.dump(yaml.load(text), stream=sys.stdout, default_flow_style=False, indent=4)

你的标量会按照你的期望行事。