【问题标题】:Can I insert a line into ruamel.yaml's CommentedMap?我可以在 ruamel.yaml 的 CommentedMap 中插入一行吗?
【发布时间】:2016-08-26 11:20:29
【问题描述】:

我知道这与this SO question 有关,但我最担心的是这是否会与保存的 cmets 等东西混淆。

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

【问题讨论】:

    标签: python yaml ordereddictionary ruamel.yaml


    【解决方案1】:

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

    因为行尾 cmets 与 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() 有一个可选参数,允许您为新插入的键值对指定注释。上述方法有效,因为从 CommentedMap 中删除密钥不会删除与该密钥关联的注释。所以我暂时把旧的键值对停在od 删除所有键值,然后在适当的时候将它们复制回去插入新的东西

    上面的insert,带有注释,已添加到ruamel.yaml 0.11.11中 Python 2 和 3


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

    【讨论】:

    • 等什么??我不知道 ruamel.ordereddict 有 .insert() :D
    • 这是可以原谅的,该软件包的作者在编写可访问的文档时是出了名的懒惰。
    • 我很高兴它完全可用。谢谢!但是即使我使用的是Python 3,我还能以某种方式使用ruamel.ordereddict吗?
    • 看着compat.py, line 12,看来我要做的就是pip install ruamel.ordereddict。这是正确的分析吗?
    • 现在位于 ruamel.yaml 0.11.11 和 documented 中。感谢您的启发。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-24
    • 1970-01-01
    • 1970-01-01
    • 2020-12-25
    • 2015-06-07
    • 1970-01-01
    相关资源
    最近更新 更多