我如何在Python中向YAML文件添加评论

我正在使用https://pypi.python.org/pypi/ruamel.yaml编写YAML文件

代码是这样的:

import ruamel.yaml
from ruamel.yaml.comments import CommentedSeq

d = {}
for m in ['B1', 'B2', 'B3']:
    d2 = {}
    for f in ['A1', 'A2', 'A3']:
        d2[f] = CommentedSeq(['test', 'test2'])
        if f != 'A2':
            d2[f].fa.set_flow_style()
    d[m] = d2

    with open('test.yml', "w") as f:
        ruamel.yaml.dump(
            d, f, Dumper=ruamel.yaml.RoundTripDumper,
            default_flow_style=False, width=50, indent=8)

我只想在顶部添加评论,如:

# Data for Class A

在YAML数据之前。


在你with块中,你可以写任何你想要的文件。 由于您只需要在顶部添加注释,请在调用f.write()之前添加对f.write()调用:

with open('test.yml', "w") as f:
    f.write('# Data for Class An')
    ruamel.yaml.dump(
        d, f, Dumper=ruamel.yaml.RoundTripDumper,
        default_flow_style=False, width=50, indent=8)

原则上这是可能的,因为你可以对这种“文件开始”注释进行往返,但是在当前的ruamel.yaml 0.10中没有得到很好的支持,当然不是在“从头开始”(即不改变现有的文件)。 底部是一个相对较好的解决方案,但我首先想提出一个丑陋的解决方法,并逐步明确如何完成这项工作。

丑陋
做这件事的丑陋的方法是在你写入YAML数据之前,将注释添加到文件中。 这是插入:

f.write('# Data for Class An')

ruamel.yaml.dump(...)之前

一步一步
为了在数据结构中插入注释,所以上面的破解不是必须的,你首先需要确保你的d数据是一个CommentedMap类型。 如果你是比较的差d变量,一个是通过加载注释YAML回有评论c

import ruamel.yaml
from ruamel.yaml.comments import Comment, CommentedSeq, CommentedMap

d = CommentedMap()             # <<<<< most important
for m in ['B1', 'B2', 'B3']:
    d2 = {}
    for f in ['A1', 'A2', 'A3']:
        d2[f] = CommentedSeq(['test', 'test2'])
        if f != 'A2':
            d2[f].fa.set_flow_style()
    d[m] = d2

yaml_str = ruamel.yaml.dump(d, Dumper=ruamel.yaml.RoundTripDumper,
                            default_flow_style=False, width=50, indent=8)

assert not hasattr(d, Comment.attrib)  # no attribute on the CommentedMap

comment = 'Data for Class A'
commented_yaml_str = '# ' + comment + 'n' + yaml_str
c = ruamel.yaml.load(commented_yaml_str, Loader=ruamel.yaml.RoundTripLoader)
assert hasattr(c, Comment.attrib)  # c has the attribute
print c.ca                         # and this is what it looks like
print d.ca                         # accessing comment attribute creates it empty
assert hasattr(d, Comment.attrib)  # now the CommentedMap has the attribute

这打印:

Comment(comment=[None, [CommentToken(value=u'# Data for Class An')]],
  items={})
Comment(comment=None,
  items={})

Comment有一个属性comment ,需要设置为由EOL注释(总是只有一个)和前面的行注释列表组成的2元素列表(以CommentTokens的形式)

要创建一个CommentToken,你需要一个(假的)StartMark来告诉它启动的是哪一列:

from ruamel.yaml.error import Mark
start_mark = Mark(None, None, None, 0, None, None)  # column 0

现在你可以创建令牌了:

from ruamel.yaml.tokens import CommentToken

ct = CommentToken('# ' + comment + 'n', start_mark, None)

将该标记指定为您的评论图上前面列表的第一个元素:

d.ca.comment = [None, [ct]]
print d.ca   # in case you want to check

给你:

Comment(comment=[None, [CommentToken(value='# Data for Class An')]],
  items={})

最后:

print ruamel.yaml.dump(d, Dumper=ruamel.yaml.RoundTripDumper)  

得到:

# Data for Class A
B1:
        A1: [test, test2]
        A3: [test, test2]
        A2:
        - test
        - test2
B2:
        A1: [test, test2]
        A3: [test, test2]
        A2:
        - test
        - test2
B3:
        A1: [test, test2]
        A3: [test, test2]
        A2:
        - test
        - test2

当然你不需要创建c对象,这只是为了说明。

你应该使用什么样的 :为了使整个运动比较容易,你可以忘掉在下面的方法的细节和补丁CommentedBase一次:

from ruamel.yaml.comments import CommentedBase

def set_start_comment(self, comment, indent=0):
    """overwrites any preceding comment lines on an object
    expects comment to be without `#` and possible have mutlple lines
    """
    from ruamel.yaml.error import Mark
    from ruamel.yaml.tokens import CommentToken
    if self.ca.comment is None:
        pre_comments = []
        self.ca.comment = [None, pre_comments]
    else:
        pre_comments = self.ca.comments[1]
    if comment[-1] == 'n':
        comment = comment[:-1]  # strip final newline if there
    start_mark = Mark(None, None, None, indent, None, None)
    for com in comment.split('n'):
        pre_comments.append(CommentToken('# ' + com + 'n', start_mark, None))

if not hasattr(CommentedBase, 'set_start_comment'): # in case it is there
    CommentedBase.set_start_comment = set_start_comment

然后就这样做:

d.set_start_comment('Data for Class A')
链接地址: http://www.djcxy.com/p/86009.html

上一篇: How can I add a comment to a YAML file in Python

下一篇: Perform code analysis in IntelliJ IDEA