Python 在数组后保留注释

Python 在数组后保留注释,python,ruamel.yaml,Python,Ruamel.yaml,这就是我的YAML的样子: yaml_str = """\ steps: - init - run - cleanup # This is a comment which needs to be preserved """ 我想做的是从步骤中删除第一个和最后一个项目,同时保留清理后的注释。即,输出需要如下所示: yaml_str = """\ steps: - run # This is a comment which needs to be preserved """

这就是我的YAML的样子:

yaml_str = """\
steps:
  - init
  - run
  - cleanup

# This is a comment which needs to be preserved
"""
我想做的是从
步骤中删除第一个和最后一个项目,同时保留
清理后的注释。即,输出需要如下所示:

yaml_str = """\
steps:
  - run

# This is a comment which needs to be preserved
"""
如何使用ruamel.yaml实现这一点

另外,据我所知,就API而言,情况与此不同:
,如果我错了,请纠正我

好的,看起来我需要使用这个结构:

已解析['steps'].ca.items[1]=已解析['steps'].ca.items.pop(2)


好的,看起来我需要使用这个结构:

已解析['steps'].ca.items[1]=已解析['steps'].ca.items.pop(2)


从YAML文件加载数据时,
ruamel.YAML
通常会附加 对正在扫描的最新集合的注释,基于密钥(在 映射的大小写)或索引(序列)

因此,在您的例子中,注释(以及行的空头和空行 在它之前)附加到序列(而不是根级别 映射)

注释当前存储在属性
ca
commentattribute)中。 因此,对于您的示例,您可以:

import sys
import ruamel.yaml

yaml_str = """\
steps:
  - init
  - run
  - cleanup

# This is a comment which needs to be preserved
"""

yaml = ruamel.yaml.YAML()
yaml.indent(sequence=4, offset=2)
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
steps = data['steps']
del steps[0]
steps.pop(-1)

yaml.dump(data, sys.stdout)
其中:

steps:
  - run

# This is a comment which needs to be preserved
Comment(comment=None,
  items={3: [CommentToken('\n\n# This is a comment which needs to be preserved\n', line: 8, col: 0), None, None, None]})
steps:
  - a: 42
    b: 39

# This is a comment which needs to be preserved
如果从序列中删除单个项,则会删除类似字典的对象 (
CommentedSeq
)足够聪明,可以“移动”注释。(你可以 在删除之前和之间插入
print(data['steps'].ca)
,以查看此信息 已发生)

这并不总是有效的,尤其是当您的 序列是一个集合。在这种情况下,您需要将注释移动到最后 该集合的元素。如果该项是序列/列表,则只需移动注释即可 但是,如果是映射/dict,则需要重新安排内容,以避免 注释出现在键和值之间:

import sys
import ruamel.yaml

yaml_str = """\
steps:
  - init
  - a: 42
    b: 39
  -   - 196
      - 3.0
  - cleanup

# This is a comment which needs to be preserved
"""

yaml = ruamel.yaml.YAML()
yaml.indent(sequence=4, offset=2)
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
steps = data['steps']

print(steps.ca)

del steps[2]  # you can comment this out to get the comment attached to 3.0

if isinstance(steps, list):
    if len(steps)-1 in steps.ca.items and len(steps) > 1 and isinstance(steps[-2], (list, dict)):
        # move the comment in advance
        tmp = steps[-2]
        ct = steps.ca.items.pop(len(steps)-1)
        if isinstance(tmp, list):
            key_tmp = len(tmp)-1
        else:
            key_tmp = list(tmp.keys())[-1]  # the final mapping key
            ct[0], ct[2] = None, ct[0]
        tmp.ca.items[key_tmp] = ct


del steps[0]
steps.pop(-1)

yaml.dump(data, sys.stdout)
其中:

steps:
  - run

# This is a comment which needs to be preserved
Comment(comment=None,
  items={3: [CommentToken('\n\n# This is a comment which needs to be preserved\n', line: 8, col: 0), None, None, None]})
steps:
  - a: 42
    b: 39

# This is a comment which needs to be preserved
请将您的代码固定在您测试此代码时使用的ruamel.yaml版本上。这类内部构件可以而且可以随意使用
一些点的改变(希望有合适的API)。

从YAML文件加载数据时,
ruamel.YAML
通常会附加 对正在扫描的最新集合的注释,基于密钥(在 映射的大小写)或索引(序列)

因此,在您的例子中,注释(以及行的空头和空行 在它之前)附加到序列(而不是根级别 映射)

注释当前存储在属性
ca
commentattribute)中。 因此,对于您的示例,您可以:

import sys
import ruamel.yaml

yaml_str = """\
steps:
  - init
  - run
  - cleanup

# This is a comment which needs to be preserved
"""

yaml = ruamel.yaml.YAML()
yaml.indent(sequence=4, offset=2)
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
steps = data['steps']
del steps[0]
steps.pop(-1)

yaml.dump(data, sys.stdout)
其中:

steps:
  - run

# This is a comment which needs to be preserved
Comment(comment=None,
  items={3: [CommentToken('\n\n# This is a comment which needs to be preserved\n', line: 8, col: 0), None, None, None]})
steps:
  - a: 42
    b: 39

# This is a comment which needs to be preserved
如果从序列中删除单个项,则会删除类似字典的对象 (
CommentedSeq
)足够聪明,可以“移动”注释。(你可以 在删除之前和之间插入
print(data['steps'].ca)
,以查看此信息 已发生)

这并不总是有效的,尤其是当您的 序列是一个集合。在这种情况下,您需要将注释移动到最后 该集合的元素。如果该项是序列/列表,则只需移动注释即可 但是,如果是映射/dict,则需要重新安排内容,以避免 注释出现在键和值之间:

import sys
import ruamel.yaml

yaml_str = """\
steps:
  - init
  - a: 42
    b: 39
  -   - 196
      - 3.0
  - cleanup

# This is a comment which needs to be preserved
"""

yaml = ruamel.yaml.YAML()
yaml.indent(sequence=4, offset=2)
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
steps = data['steps']

print(steps.ca)

del steps[2]  # you can comment this out to get the comment attached to 3.0

if isinstance(steps, list):
    if len(steps)-1 in steps.ca.items and len(steps) > 1 and isinstance(steps[-2], (list, dict)):
        # move the comment in advance
        tmp = steps[-2]
        ct = steps.ca.items.pop(len(steps)-1)
        if isinstance(tmp, list):
            key_tmp = len(tmp)-1
        else:
            key_tmp = list(tmp.keys())[-1]  # the final mapping key
            ct[0], ct[2] = None, ct[0]
        tmp.ca.items[key_tmp] = ct


del steps[0]
steps.pop(-1)

yaml.dump(data, sys.stdout)
其中:

steps:
  - run

# This is a comment which needs to be preserved
Comment(comment=None,
  items={3: [CommentToken('\n\n# This is a comment which needs to be preserved\n', line: 8, col: 0), None, None, None]})
steps:
  - a: 42
    b: 39

# This is a comment which needs to be preserved
请将您的代码固定在您测试此代码时使用的ruamel.yaml版本上。这类内部构件可以而且可以随意使用
一些点的改变(希望有一个合适的API)。

是的,这看起来是正确的。注释与它们后面的项目相关联,行尾注释被视为以空行和仅进一步注释的行继续。我会使用
parsed['steps'].ca.items[-2]=parsed['steps'].ca.items.pop(-1)
将最后一项上的注释移动到之前的注释。谢谢@Anthon。我现在面临的唯一问题是一个数组,其中一个元素(中间一个)是映射(其他元素只是字符串)。希望也能解决。干杯,看起来不错。注释与它们后面的项目相关联,行尾注释被视为以空行和仅进一步注释的行继续。我会使用
parsed['steps'].ca.items[-2]=parsed['steps'].ca.items.pop(-1)
将最后一项上的注释移动到之前的注释。谢谢@Anthon。我现在面临的唯一问题是一个数组,其中一个元素(中间一个)是映射(其他元素只是字符串)。希望也能解决。干杯