在 PyYAML 中保存/转储带有注释的 YAML 文件

Posted

技术标签:

【中文标题】在 PyYAML 中保存/转储带有注释的 YAML 文件【英文标题】:Save/dump a YAML file with comments in PyYAML 【发布时间】:2011-11-07 12:37:01 【问题描述】:

我有一个如下所示的 yaml 文件:

# The following key opens a door
key: value

有什么方法可以在维护评论的同时loaddump 这些数据?

【问题讨论】:

我曾经修改过 C libyaml 代码以发出 cmets 供我自己使用。将其扩展到 PyYAML 并不容易。 我又想到了这个。解析和编写一个手动编辑的yaml文件有意义吗(将来会手动编辑)?为什么不将文件分成两部分:一份是手工制作的,另一部分是纯数据(没有 cmets)。相关:github.com/guettli/programming-guidelines/blob/master/… 【参考方案1】:

PyYAML 以非常低的级别丢弃 cmets(在 Scanner.scan_to_next_token 中)。

虽然您可以对其进行调整或扩展以处理整个堆栈中的 cmets,但这将是一项重大修改。 Dumping(=发射)cmets 似乎更容易,并在旧的 PyYAML 错误跟踪器上的 ticket 114 中进行了讨论。

截至 2020 年,关于添加对加载 cmets 的支持的 feature request 仍然停滞不前。

【讨论】:

你说得对,这是一个重大修改,虽然更容易,因为我放弃了 【参考方案2】:

如果您使用的是块结构的 YAML,则可以使用 python 包¹ruamel.yaml,它是 PyYAML 的衍生产品,支持 cmets 的往返保存

import sys
import ruamel.yaml

yaml_str = """\
# example
name:
  # details
  family: Smith   # very common
  given: Alice    # one of the siblings
"""

yaml = ruamel.yaml.YAML()  # defaults to round-trip if no parameters given
code = yaml.load(yaml_str)
code['name']['given'] = 'Bob'

yaml.dump(code, sys.stdout)

结果:

# example
name:
  # details
  family: Smith   # very common
  given: Bob      # one of the siblings

请注意,行尾 cmets 仍然对齐。

code 不是普通的 listdict 对象,而是由附加 cmets 的包装版本²组成。

¹ 使用pip install ruamel.yaml 安装。适用于 Python 2.6/2.7/3.3+ ² ordereddict 用于映射,以保持排序

【讨论】:

这不能回答 OP 的问题。它保留顺序,但不保留 cmets。 @cerin 运行上述代码时缺少哪些 cmets?使用哪个版本的 Python、ruamel.yaml 以及在哪个平台上运行此代码?我只是用最新版本的 ruamel.yaml 重试了这个(以防我弄坏了东西),输出仍然包括 cmets。鉴于这里的赞成票数量,我认为其他人已经能够获得相同的结果,而您可能忽略了一些事情。 @Anthon,似乎不一致。在您的示例中,保留了 cmets,但是在我测试过的更复杂的 yaml 文件中,它会删除一些 cmets,尤其是在您编辑这些 cmets 附近的数据时。我正在使用最新版本的 Python 2.7 包。 @cerin 往返最初是为了更新配置文件中的值,这应该始终有效。事物被“保留”的方式,如果您开始删除键,那么 cmets 可能会消失。如果您在Stack Overflow 上询问有关此问题或提交错误报告,我更愿意。如果可以的话,我倾向于解决问题,并尝试给出解决方法,或者如果我不能,至少给出一个解释。 如果有人想要更标准的 YAML 格式,你可以在做 dump 之前使用 yaml.indent(mapping=2, sequence=4, offset=2)【参考方案3】:

我有一个 pyyaml 分支可以做到这一点。 https://github.com/pflarr/pyyaml

要使用 cmets 构建 yaml 文件,您必须创建一个包含评论事件的事件流。目前仅允许在序列项和映射键之前进行注释。

目前这仅适用于 python3,我还没有将它移植到库的 python2 版本,但可以根据要求轻松完成。此外,这也应该很容易移植到 C libyaml,因为无论如何,python 代码都是一个简单的移植。

【讨论】:

以上是关于在 PyYAML 中保存/转储带有注释的 YAML 文件的主要内容,如果未能解决你的问题,请参考以下文章

向使用 PyYaml 生成的 YAML 添加注释

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

为 PyYAML 转储的一部分指定样式

PyYaml - 使用特殊字符(即重音符号)转储 unicode

Python的PyYAML模块详解

pyyaml 的漂亮输出