如何在不使用yaml.dump的情况下替换yaml文件中的字典值[关闭]

问题描述 投票:1回答:1

我有一个yml文件,例如abc.yml

 a: 1
 b:2
 c:
  c1:
  -  c2: '0'
     c3: '00'
  c11:
  -  c21: '1'
     c31: '11'

我还有其他文件config.properties

a:1
b:2
c:
 c1:
  - c2: '7'
     c3: '77'
  c11:
  -  c21: '8'
     c31: '88'

我只想用config.properties替换abc.yml文件中的一些值,只说值c。我正在做的是,我用config.properties的键值创建了字典dict1,而用abc.yml文件的键值创建了dict2。然后,我比较了键并更新了dict3中的值。现在我只想替换c的值,但是当我使用yaml.dump(dict3)时,它将用某些值替换整个文件。这是我的代码。

dict1 = {}
with open('confg.properties', 'r') as f:
  for line in f:
      k, v = line.split(":", 1)

with open('abc.yml') as f:
  dict2 = yaml.load(f, Loader=yaml.FullLoader)

dict3 = {}
for k1, v1 in dict2.items():
  for k, v in dict1.items():
    if k1 == k:
      dict3[k1] = v

with open('abc.yml', 'w') as f:   
   data = yaml.dump(dict3, f) 

这是仅用某些值替换完整文件。我不想替换完整文件。

我希望将abc.yml输出为

a:1
b:2
c:
 c1:
  - c2: '7'
    c3: '77'
 c11:
  -  c21: '8'
     c31: '88'

我的代码输出为:abc.yml为:

c1:
  - c2: '7'
    c3: '77'
 c11:
  -  c21: '8'
     c31: '88'
python python-3.x pyyaml
1个回答
0
投票

您的代码和数据有多个问题。

  1. 您的输入abc.yml是无效的YML(它是XML派生),并且它也是无效的YAML,假设后者是您要在映射中使用的(b:2\nc)。

    由于您指出了代码转储,所以您没有向我们提供您提供的abc.yml(原文如此!),除非代码的缺失部分(导入yaml的那一部分)做了某些工作,以便PyYAML可以处理这种无效的格式),或者第二行实际读取的是b: 2(我认为是后者)。

  2. 您提供了config.properties,但是您的代码读取了confgi.properties(在@Amiram编辑期间,@ Amiram对其进行了整理)。由于我们不知道后者的内容,因此可能会发生很多错误。

  3. 您期望的输出是无效的YAML,因为您不能具有多行键a:1\nb:2\nc(但我认为应该是三个不同的映射条目)。

  4. 您的输出中序列条目的缩进不一致:键c2的映射缩进了四个位置,序列指示器的偏移量为2,键c21的映射缩进了五个位置,且两个的偏移量。 PyYAML无法为您提供该输出。

    除了您的映射仅缩进一个位置(相对于c1c,PyYAML不支持与序列缩进的区分。

  5. 您覆盖您的输入文件,在测试过程中总是很棘手,因此,假设您的代码运行了,条目将从abc.yml

由于我们不知道confgi.properties(您在代码中实际使用的文件),所以一切顺利,但是市长的问题是您这样做:

k, v = line.split(":", 1)

在完整的输入行上。因此,对于k中的任何缩进行,生成的-将具有前导字符(空格和[或C0])。

另一方面,键confgi.properties的值(v)当然是空字符串。


强烈建议:

  1. 您将配置文件更改为有效的YAML并以此方式加载,以防止加载带前导空格的键。

  2. 切换为使用ruamel.yaml(免责声明:我是该软件包的作者),对输出格式的更精细控制

  3. 以包含YAML和配置输入的自包含文件开始,因此您不能意外地覆盖了您的输入并失去了对正在使用的数据的跟踪(您始终可以阅读一切正常后,从文件中写入文件)

尝试类似的东西:

c1

给出:

import sys
import ruamel.yaml

yaml_str = """\
 a: 1
 b: 4
 c:
  c1:
  -  c2: '0'
     c3: '00'
  c11:
  -  c21: '1'
     c31: '11'
"""

config_str = """\
a: 1
b: 2
c:
 c1:
  - c2: '7'
    c3: '77'
 c11:
  - c21: '8'
    c31: '88'
"""

yaml = ruamel.yaml.YAML()
yaml.indent(mapping=1, sequence=4, offset=2)
data = yaml.load(yaml_str)
cfg = yaml.load(config_str)
for k1, v1 in data.items():
    for k, v in cfg.items():
        if k1 == k:
            data[k1] = v
yaml.dump(data, sys.stdout)
© www.soinside.com 2019 - 2024. All rights reserved.