我可以在 ruamel.yaml 的 CommentedMap 中插入一行吗?
Can I insert a line into ruamel.yaml's CommentedMap?
我知道这与 this 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...
在 Python 2.7 和 Python 3.X 上至少 ruamel.yaml 0.11.11,这工作正常:
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
中的行键相关联。 (Python 2.7.11 在 Linux Mint 上 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=正确,...)
我知道这与 this 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...
在 Python 2.7 和 Python 3.X 上至少 ruamel.yaml 0.11.11,这工作正常:
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
中的行键相关联。 (Python 2.7.11 在 Linux Mint 上 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=正确,...)