python - pyyaml 的漂亮输出

标签 python yaml pretty-print pyyaml

我有一个 python 项目,我想在其中使用 YAML (pyYaml 3.11),特别是因为它“漂亮”并且用户可以在必要时轻松地在文本编辑器中进行编辑。不过,我的问题是,如果我将 YAML 引入 python 应用程序(因为我需要这样做)并编辑内容(因为我需要这样做),那么编写新文档通常不像我开始时那样漂亮。

pyyaml 文档非常糟糕——甚至没有记录转储函数的参数。我找到了 http://dpinte.wordpress.com/2008/10/31/pyaml-dump-option/ .但是,我仍然缺少我需要的信息。 (我开始查看源代码,但它似乎不是最吸引人的。如果我在这里没有得到解决方案,那是我唯一的办法。)

我从一个看起来像这样的文档开始:

- color green :
     inputs :
        - port thing :
            widget-hint : filename
            widget-help : Select a filename
        - port target_path : 
            widget-hint : path
            value : 'thing' 
     outputs:
        - port value:
             widget-hint : string
     text : |
            I'm lost and I'm found
            and I'm hungry like the wolf.

加载到 python (yaml.safe_load(s)) 后,我尝试了几种将其转储出来的方法:

>>> print yaml.dump( d3, default_flow_style=False, default_style='' )
- color green:
    inputs:
    - port thing:
        widget-help: Select a filename
        widget-hint: filename
    - port target_path:
        value: thing
        widget-hint: path
    outputs:
    - port value:
        widget-hint: string
    text: 'I''m lost and I''m found

      and I''m hungry like the wolf.

      '
>>> print yaml.dump( d3, default_flow_style=False, default_style='|' )
- "color green":
    "inputs":
    - "port thing":
        "widget-help": |-
          Select a filename
        "widget-hint": |-
          filename
    - "port target_path":
        "value": |-
          thing
        "widget-hint": |-
          path
    "outputs":
    - "port value":
        "widget-hint": |-
          string
    "text": |
      I'm lost and I'm found
      and I'm hungry like the wolf.

理想情况下,我希望“短字符串”不使用引号,就像在第一个结果中那样。但我希望将多行字符串写成 block ,就像第二个结果一样。我想从根本上说,我正在尝试尽量减少文件中不必要引号的激增,我认为这会使在文本编辑器中编辑变得更加烦人。

有没有人有这方面的经验?

最佳答案

如果你可以使用 ruamel.yaml(免责声明:我是这个增强版 PyYAML 的作者)你可以 往返原始格式(YAML 文档存储在文件 org.yaml 中):

import sys
import ruamel.yaml
from pathlib import Path

file_org = Path('org.yaml')
    
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
data = yaml.load(file_org)
yaml.dump(data, sys.stdout)

给出:

- color green:
    inputs:
    - port thing:
        widget-hint: filename
        widget-help: Select a filename
    - port target_path:
        widget-hint: path
        value: 'thing'
    outputs:
    - port value:
        widget-hint: string
    text: |
      I'm lost and I'm found
      and I'm hungry like the wolf.

您输入的缩进/格式不一致,尽管在 ruamel.yaml 中有更多控制 输出比在 PyYAML 中的输出,你无法得到准确的原始数据:

  • 您有时 (color green :) 在值指示符 (:) 之前有一个空格,有时您 不要(输出:)。除了对根级别 key 的特殊控制外,ruamel.yaml 始终将 值指示符直接与键相邻。
  • 您的根级序列缩进两列, block 序列指示符 (-) 的偏移量为零 (这是默认的 ruamel.yaml 使用)。其他缩进五,三个偏移。 ruamel.yaml 不能单独/不一致地格式化序列,我建议使用默认值,因为你的根 集合是一个序列。
  • 您的映射有时会缩进三列(key color green 的值)有时 两个(例如键 port target_path 的值)。同样,ruamel.yaml 无法单独/不一致地格式化这些内容
  • 如果你 不要将 block 缩进指示符附加到 | 指示符(例如使用 |4)。所以这 额外的缩进将丢失

如您所见,设置 yaml.preserv_quotes 会保留 'thing' 周围多余的引号 不是你想要的,它没有在这个例子的其余部分设置。

以下“规范化”了所有三个示例:

import sys
import ruamel.yaml
from pathlib import Path
LT = ruamel.yaml.scalarstring.LiteralScalarString

file_org = Path('org.yaml')
file_plain = Path('plain.yaml')
file_block = Path('block.yaml')

def normalise(d):
    if isinstance(d, dict):
        for k, v in d.items():
             d[k] = normalise(v)
        return d
    if isinstance(d, list):
        for idx, elem in enumerate(d):
            d[idx] = normalise(elem)
        return d
    if not isinstance(d, str):
        return d
    if '\n' in d:
        if isinstance(d, LT):
            return d     # already a block style literal scalar
        return LT(d)
    return str(d)

yaml = ruamel.yaml.YAML()
for fn in [file_org, file_plain, file_block]:
    data = normalise(yaml.load(file_org))
    yaml.dump(data, fn)

assert file_org.read_bytes() == file_plain.read_bytes()
assert file_org.read_bytes() == file_block.read_bytes()
print(file_block.read_text())

给出:

- color green:
    inputs:
    - port thing:
        widget-hint: filename
        widget-help: Select a filename
    - port target_path:
        widget-hint: path
        value: thing
    outputs:
    - port value:
        widget-hint: string
    text: |
      I'm lost and I'm found
      and I'm hungry like the wolf.

因此,正如您所指出的,如果标量有换行符,您将获得 block 样式文字标量,并且 如果是标量,则没有 block 样式 没有引号 它没有换行符。

关于python - pyyaml 的漂亮输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24418449/

相关文章:

google-app-engine - Google App Engine、Jinja2 CSS 样式表未加载 (404)

curl - 如何在curl中使用原始YAML文件创建Pod

xml - 在属性之间添加换行符

Python boto - 如何获取弹性 ip 的分配 id

python - 从 dict 中检索对象,以便可以通过 json.dumps() 轻松转储该对象

amazon-web-services - 使用 YAML 设置 S3 存储桶的问题

java - 我如何缩进生成的java代码java?

c++ - 在 C++ 代码上使用 astyle 删除空格并添加换行符

python - 在这种情况下如何使用正则表达式更改 pandas 列名称?

python - 将某些列除以 Pandas 中的另一列