7

我知道这与这个 SO question 有关,但我最关心的是这是否会与保留的评论之类的东西混淆。

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))
应该输出:
first_name: Art
last_name: Vandelay
occupation: Architect  # This is an occupation comment
about: Art Vandelay is a fictional character that George invents...
不应输出
first_name: Art
last_name: Vandelay    # This is an occupation comment
occupation: Architect
about: Art Vandelay is a fictional character that George invents...
4

1 回答 1

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))

给出:

first_name: Art
last name: Vandelay
occupation: Architect  # This is an occupation comment
about: Art Vandelay is a fictional character that George invents...

因为行尾注释与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))

在 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...

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

insertruamel.yaml 0.11.11 中已为 Python 2 和 3 添加了上述内容和注释


.round_trip_load()等价于.load(...., Loader=ruamel.yaml.RoundTripLoader, ...)和` .dump .round_trip_dump()(....., Dumper=ruamel.yaml.RoundTripDumper, allow_unicode=True, ...)

于 2016-05-01T18:52:11.413 回答