在ruamel.yaml 中,YAML() 实例仅将信息保存到
分别加载转储您的 YAML 文档。 它不允许您访问
cmets,因为它不会将它们存储在实例中。
正如您所指出的,ruamel.yaml 可以转储 cmets,因此他们必须
在某个地方,它们确实是:附加到对象层次结构中
由YAML.load() 创建。而你需要做的是递归地走
为获取附加的 cmets 而加载的数据结构。
对于当前连接 cmets 的方式,如下所示:
import sys
import ruamel.yaml
from ruamel.yaml.tokens import CommentToken
yaml_str = """\
a:
b:
- elem1 # this is the first comment
- elem2 # this is the second comment
c:
d: 42 # this is not the 42nd comment
"""
def extract_from_token(tl):
assert isinstance(tl, list)
for t in tl:
if t is None:
continue
yield t.start_mark.line, t.value
def get_yaml_comments(d):
if isinstance(d, dict):
if d.ca.comment is not None:
for l, c in extract_from_token(d.ca.comment):
yield l, c
for key, val in d.items():
for l, c in get_yaml_comments(val):
yield l, c
if key in d.ca.items:
for l, c in extract_from_token(d.ca.items[key]):
yield l, c
elif isinstance(d, list):
if d.ca.comment is not None:
for l, c in extract_from_token(d.ca.comment):
yield l, c
for idx, item in enumerate(d):
for l, c in get_yaml_comments(item):
yield l, c
if idx in d.ca.items:
for l, c in extract_from_token(d.ca.items[idx]):
yield l, c
yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
for line, comment in get_yaml_comments(data):
print(f"{comment!r} ({line})")
给出:
'# this is the first comment\n' (2)
'# this is the second comment\n' (3)
'# this is not the 42nd comment \n' (5)