我可以在ruamel.yaml的CommentedMap中插入一行吗?

dem*_*mux 5 python yaml ordereddictionary ruamel.yaml

我知道这与这个问题有关,但我最关心的是这是否可能会混淆诸如保留的评论等内容.

import ruamel.yaml as yaml

yaml_str = """\
first_name: Art
occupation: Architect  # This is an occupation comment
about: Art Vandelay is a fictional character that George invents...
"""

data = yaml.load(yaml_str, Loader=yaml.RoundTripLoader)

# I'd like to extend CommentedMap so that I can do something like:
data.insert(1, 'last_name', 'Vandelay')

print(yaml.dump(data, Dumper=yaml.RoundTripDumper))
Run Code Online (Sandbox Code Playgroud) 应输出:
first_name: Art
last_name: Vandelay
occupation: Architect  # This is an occupation comment
about: Art Vandelay is a fictional character that George invents...
Run Code Online (Sandbox Code Playgroud) 如若不是输出:
first_name: Art
last_name: Vandelay    # This is an occupation comment
occupation: Architect
about: Art Vandelay is a fictional character that George invents...
Run Code Online (Sandbox Code Playgroud)

Ant*_*hon 4

在 Python 2.7 和至少具有 ruamel.yaml 0.11.11 的 Python 3.X 上,这可以正常工作:

import ruamel.yaml

yaml_str = """\
first_name: Art
occupation: Architect  # This is an occupation comment
about: Art Vandelay is a fictional character that George invents...
"""

data = ruamel.yaml.round_trip_load(yaml_str)
data.insert(1, 'last name', 'Vandelay')

print(ruamel.yaml.round_trip_dump(data))
Run Code Online (Sandbox Code Playgroud)

给出:

first_name: Art
last name: Vandelay
occupation: Architect  # This is an occupation comment
about: Art Vandelay is a fictional character that George invents...
Run Code Online (Sandbox Code Playgroud)

因为行尾注释与CommentedMap. (Linux Mint 上的 Python 2.7.11 和 ruamel.yaml 0.11.10。)

这不适用于 Python3 的旧版本 ruamel.yaml,因为.insert()您正在使用的是成熟的功能ruamel.ordereddict,而标准库中的 OrderedDict 没有该方法。因此,您需要将一个.insert()函数移植到CommentedMap

import ruamel.yaml
from ruamel.yaml.comments import CommentedMap
from ruamel.yaml.compat import ordereddict

yaml_str = """\
first_name: Art
occupation: Architect  # This is an occupation comment
about: Art Vandelay is a fictional character that George invents...
"""

def com_insert(self, pos, key, value, comment=None):
    od = ordereddict()
    od.update(self)
    for k in od:
        del self[k]
    for index, old_key in enumerate(od):
        if pos == index:
            self[key] = value
        self[old_key] = od[old_key]
    if comment is not None:
        self.yaml_add_eol_comment(comment, key=key)

CommentedMap.insert = com_insert

data = ruamel.yaml.round_trip_load(yaml_str)
data.insert(1, 'last name', 'Vandelay', comment="new key")

print(ruamel.yaml.round_trip_dump(data))
Run Code Online (Sandbox Code Playgroud)

在 Python3 上给出:

first_name: Art
last name: Vandelay    # new key
occupation: Architect  # This is an occupation comment
about: Art Vandelay is a fictional character that George invents...
Run Code Online (Sandbox Code Playgroud)

请注意,有一个可选参数insert()允许您为新插入的键值对指定注释。上面的方法之所以有效,是因为从 a 中删除键CommentedMap并不会删除与该键关联的注释。所以我暂时将旧的键值对od 删除所有键值,然后将它们复制回来,在适当的时候插入新的东西

上面的内容insert(带注释)已添加到 Python 2 和 3 的 ruamel.yaml 0.11.11 中


相当于.round_trip_load()` .load(...., Loader=ruamel.yaml.RoundTripLoader, ...).dump .round_trip_dump()(....., Dumper=ruamel.yaml.RoundTripDumper, allowed_unicode=True, ...)

  • 这是情有可原的,该包的作者在编写可访问的文档时是出了名的懒惰。 (3认同)
  • 现在它位于 ruamel.yaml 0.11.11 和[记录](http://yaml.readthedocs.io/en/latest/example.html)中。感谢您的灵感。 (3认同)