Python 有没有办法强制ruamel在换行符之前在OrderedDict中插入一个新的(键:值)对?

Python 有没有办法强制ruamel在换行符之前在OrderedDict中插入一个新的(键:值)对?,python,ruamel.yaml,Python,Ruamel.yaml,有了下面的代码片段,我将尝试更新“a”下的每个3x ordereddict对象: import sys from ruamel.yaml import round_trip_load, round_trip_dump s=""" a: - b: c - d: e - f: g """ yaml_obj=round_trip_load(s) yaml_sub_obj = [x for x in yaml_obj['a']] for sub_obj in yaml_sub_obj: su

有了下面的代码片段,我将尝试更新“a”下的每个3x ordereddict对象:

import sys
from ruamel.yaml import round_trip_load, round_trip_dump
s="""
a:
- b: c

- d: e
- f: g
"""
yaml_obj=round_trip_load(s)
yaml_sub_obj = [x for x in yaml_obj['a']]

for sub_obj in yaml_sub_obj:
    sub_obj.insert(1, "new_key", "new_value")
当使用
往返转储(yaml\u obj,sys.stdout)
时,我期待下面的输出(空行应该在第一个子元素的最后一个键值对之后):

但是,使用
往返转储(yaml\u obj,sys.stdout)
转储初始对象时,将显示:

a:
- b: c

  new_key: new_value
- d: e
  new_key: new_value
- f: g
  new_key: new_value
2) 如果已经存在键,则更新对象的行为是可以的,但我不想强制存在此(键/空_值)对,因为我正在处理的YAML有点复杂,我希望自动填充它们:

s2="""
a:
 - b: c
   new_key:

 - c: d
   new_key:

 - e: f
   new_key:
"""
y = round_trip_load(s2)
for s in y["a"]:
     s["new_key"]="new_value"
再次倾倒看起来很好:

a:
- b: c
  new_key: new_value

- c: d
  new_key: new_value

- e: f
  new_key: new_value

我在0.16.5上看到了这种行为,但是我将ruamel.yaml升级到了0.16.10,并且行为是相同的。如果未指定流样式,这是预期行为吗?

您的预期不正确。如其他位置所示(例如。 )在ruamel.yaml评论中 与以前的节点关联,这些节点由 映射的键(或序列的索引)

和整行注释,以及空行当前被处理为前一行结束注释的延续,无论 这些EOL注释是否存在

除此之外,您应该考虑使用已经存在很长时间的新API,而不是
往返加载
/
dump()
函数

import sys
import ruamel.yaml

yaml_str = """\
a:
- b: c

- d: e
- f: g
"""

yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
for sub_obj in data['a']:
    index = 1
    new_key = "new_key"
    prev_key = list(sub_obj.keys())[index-1]
    sub_obj.insert(index, new_key, "new_value")
    try:
        sub_obj.ca.items[new_key] = sub_obj.ca.items.pop(prev_key)
    except KeyError:
        pass
yaml.dump(data, sys.stdout)
其中:

a:
- b: c
  new_key: new_value

- d: e
  new_key: new_value
- f: g
  new_key: new_value
a:
- b: c  # some comment
  new_key: new_value

# this is to make an emtpy line more clearly visible
- d: e
  new_key: new_value
- f: g
  new_key: new_value
如果您有具体的行末注释,那么 您不应该弹出
prev_键
,而是复制它并拆分它的第三个元素

import sys
from copy import deepcopy
import ruamel.yaml

yaml_str = """\
a:
- b: c  # some comment

# this is to make an emtpy line more clearly visible
- d: e
- f: g
"""

yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
for sub_obj in data['a']:
    index = 1
    new_key = "new_key"
    prev_key = list(sub_obj.keys())[index-1]
    sub_obj.insert(index, new_key, "new_value")
    try:
        comment = sub_obj.ca.items[prev_key]
        new_comment = deepcopy(comment)
        comment[2].value, rest = comment[2].value.split('\n', 1)
        new_comment[2].value = '\n' + rest
        sub_obj.ca.items[new_key] = new_comment
    except KeyError:
        pass
yaml.dump(data, sys.stdout)
其中:

a:
- b: c
  new_key: new_value

- d: e
  new_key: new_value
- f: g
  new_key: new_value
a:
- b: c  # some comment
  new_key: new_value

# this is to make an emtpy line more clearly visible
- d: e
  new_key: new_value
- f: g
  new_key: new_value
请注意,这不是一个用于处理评论的已发布API,可以/将 更改,因此请锁定适合您的应用程序的ruamel.yaml版本
项目。

您的期望不正确。如其他位置所示(例如。 )在ruamel.yaml评论中 与以前的节点关联,这些节点由 映射的键(或序列的索引)

和整行注释,以及空行当前被处理为前一行结束注释的延续,无论 这些EOL注释是否存在

除此之外,您应该考虑使用已经存在很长时间的新API,而不是
往返加载
/
dump()
函数

import sys
import ruamel.yaml

yaml_str = """\
a:
- b: c

- d: e
- f: g
"""

yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
for sub_obj in data['a']:
    index = 1
    new_key = "new_key"
    prev_key = list(sub_obj.keys())[index-1]
    sub_obj.insert(index, new_key, "new_value")
    try:
        sub_obj.ca.items[new_key] = sub_obj.ca.items.pop(prev_key)
    except KeyError:
        pass
yaml.dump(data, sys.stdout)
其中:

a:
- b: c
  new_key: new_value

- d: e
  new_key: new_value
- f: g
  new_key: new_value
a:
- b: c  # some comment
  new_key: new_value

# this is to make an emtpy line more clearly visible
- d: e
  new_key: new_value
- f: g
  new_key: new_value
如果您有具体的行末注释,那么 您不应该弹出
prev_键
,而是复制它并拆分它的第三个元素

import sys
from copy import deepcopy
import ruamel.yaml

yaml_str = """\
a:
- b: c  # some comment

# this is to make an emtpy line more clearly visible
- d: e
- f: g
"""

yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
for sub_obj in data['a']:
    index = 1
    new_key = "new_key"
    prev_key = list(sub_obj.keys())[index-1]
    sub_obj.insert(index, new_key, "new_value")
    try:
        comment = sub_obj.ca.items[prev_key]
        new_comment = deepcopy(comment)
        comment[2].value, rest = comment[2].value.split('\n', 1)
        new_comment[2].value = '\n' + rest
        sub_obj.ca.items[new_key] = new_comment
    except KeyError:
        pass
yaml.dump(data, sys.stdout)
其中:

a:
- b: c
  new_key: new_value

- d: e
  new_key: new_value
- f: g
  new_key: new_value
a:
- b: c  # some comment
  new_key: new_value

# this is to make an emtpy line more clearly visible
- d: e
  new_key: new_value
- f: g
  new_key: new_value
请注意,这不是一个用于处理评论的已发布API,可以/将 更改,因此请锁定适合您的应用程序的ruamel.yaml版本
项目。

AFAICT
flow\u style
即使使用旧式例程,也不会影响此行为。AFAICT
flow\u style
即使使用旧式例程,也不会影响此行为。谢谢你,Anthon!我对你的回答投了赞成票。它解决了那个特殊的问题,我试着从我的“现实生活”问题开始尽可能地简化这个问题。我的yaml更复杂,没有“new_value”,而是嵌套字典(例如:“new_key”:{“new_dict_key”:“new_dict_value”})。因此,空行将显示在“new_key”之后,但在“new_dict_key”之前,这显然是意料之中的:a:-b:c#一些注释new_key:#这是为了使空行更清晰可见new_dict_key:new_dict_value我将尝试使用新API挖掘更多内容。谢谢!谢谢你,安顿!我对你的回答投了赞成票。它解决了那个特殊的问题,我试着从我的“现实生活”问题开始尽可能地简化这个问题。我的yaml更复杂,没有“new_value”,而是嵌套字典(例如:“new_key”:{“new_dict_key”:“new_dict_value”})。因此,空行将显示在“new_key”之后,但在“new_dict_key”之前,这显然是意料之中的:a:-b:c#一些注释new_key:#这是为了使空行更清晰可见new_dict_key:new_dict_value我将尝试使用新API挖掘更多内容。谢谢!