在 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
有什么方法可以在维护评论的同时load
和dump
这些数据?
【问题讨论】:
我曾经修改过 C libyaml 代码以发出 cmets 供我自己使用。将其扩展到 PyYAML 并不容易。 我又想到了这个。解析和编写一个手动编辑的yaml文件有意义吗(将来会手动编辑)?为什么不将文件分成两部分:一份是手工制作的,另一部分是纯数据(没有 cmets)。相关:github.com/guettli/programming-guidelines/blob/master/… 【参考方案1】:PyYAML 以非常低的级别丢弃 cmets(在 Scanner.scan_to_next_token
中)。
虽然您可以对其进行调整或扩展以处理整个堆栈中的 cmets,但这将是一项重大修改。 Dump
ing(=发射)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
不是普通的 list
和 dict
对象,而是由附加 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 文件的主要内容,如果未能解决你的问题,请参考以下文章