pyyaml 的漂亮输出

Posted

技术标签:

【中文标题】pyyaml 的漂亮输出【英文标题】:pretty output with pyyaml 【发布时间】:2014-08-16 14:14:58 【问题描述】:

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

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

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

- 绿色: 输入: - 港口的东西: 小部件提示:文件名 小部件帮助:选择一个文件名 - 端口目标路径: 小部件提示:路径 价值:'东西' 输出: - 端口值: 小部件提示:字符串 文字:| 我迷路了,我找到了 我饿得像狼一样。

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

>>> 打印 yaml.dump(d3, default_flow_style=False, default_style='' ) - 绿色: 输入: - 港口的东西: 小部件帮助:选择一个文件名 小部件提示:文件名 - 端口目标路径: 价值:东西 小部件提示:路径 输出: - 端口值: 小部件提示:字符串 文字:“我迷路了,我找到了” 我饿得像狼一样。 ' >>> 打印 yaml.dump(d3, default_flow_style=False, default_style='|' ) - “绿色”: “输入”: - “港口事物”: “小部件帮助”:|- 选择文件名 “小部件提示”:|- 文件名 - “端口目标路径”: “价值”:|- 事物 “小部件提示”:|- 小路 “输出”: - “端口值”: “小部件提示”:|- 细绳 “文本”:| 我迷路了,我找到了 我饿得像狼一样。

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

有人有这方面的经验吗?

【问题讨论】:

【参考方案1】:

如果你可以使用ruamel.yaml(免责声明:我是这个PyYAML增强版的作者)你可以这样做:

import ruamel.yaml

yaml_str = """\
- 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.
"""

data = ruamel.yaml.round_trip_load(yaml_str)
res = ""
for line in ruamel.yaml.round_trip_dump(data, indent=5, block_seq_indent=3).splitlines(True):
    res += line[3:]
print(res)

你得到:

- 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 的更新版本,您可以在该缩进中设置序列- 的缩进和相对缩进。然而,后者也会影响您的***序列,因此也会影响后期处理。

保留的重要(对我而言)内容:cmets、锚点、映射合并和文字标量(使用| 的多行)

【讨论】:

@AndySmith 好的。让我们删除这些 cmets,因为它们不会帮助任何人。 如果没有 yaml 文件来调用往返吗? @oulenz 这取决于你对简单的定义,你当然必须有一些规则(例如,任何包含换行符的字符串都应该是文字块标量;任何没有空格的都应该不加引号)如果你不想手动使用这些。如果您有兴趣完成这项工作,为什么不在 SO 上提出问题? 我现在正在使用 ***.com/a/33300001 。我曾希望您可能为此提供了一个选项,因为这似乎是许多人想要的。我对各种边缘情况不够熟悉,无法理解没有明确的实现。 @oulenz 我的回答可能需要一些更新。【参考方案2】:

试试pyaml 漂亮的打印机。它更接近了,尽管它确实在短字符串周围加上了引号,其中包含空格:

>>> print pyaml.dump(d3)
- '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.

【讨论】:

如果其他人阅读此评论并徒劳地试图找到yaml.dump()pretty_print 选项...此评论指的是不太标准的pyaml 包(使用import pyaml 导入),而不是更标准的 PyYAML(使用 import yaml 导入)。

以上是关于pyyaml 的漂亮输出的主要内容,如果未能解决你的问题,请参考以下文章

强制 pyYAML 持续转储

pyyaml 并仅对字符串使用引号

PyYAML文档

PyYAML 可以按非字母顺序转储 dict 项目吗?

为啥致命错误:安装 PyYAML 时找不到“yaml.h”文件?

PyYAML 转储格式