Python:在YAML文件中替换字符串

时间:2019-02-21 09:25:25

标签: python yaml pyyaml

我有以下示例YAML文件:

---
test:
  name: "Tom"
  age: "5"
  version: "1.0"

如何将此YAML文件替换为此:


test:
  name: "Max"
  age: "10"
  version: "2.2"

这是我打开文件的方式:

import yaml

with open("config.yml", 'r') as stream:
        print(yaml.load(stream))

但是我不知道如何立即编辑YAML文件。

2 个答案:

答案 0 :(得分:2)

鉴于您使用PyYaml的事实,执行此操作的适当方法如下:

#!/usr/bin/env python

import yaml

with open("testfile.yaml", 'r') as stream:
    try:
        loaded = yaml.load(stream)
    except yaml.YAMLError as exc:
        print(exc)

# Modify the fields from the dict
loaded['test']['name'] = "Max"
loaded['test']['age'] = "10"
loaded['test']['version'] = "2.2"

# Save it again
with open("modified.yaml", 'w') as stream:
    try:
        yaml.dump(loaded, stream, default_flow_style=False)
    except yaml.YAMLError as exc:
        print(exc)

因此,您只需将Yaml加载到名为dict的{​​{1}}中,然后修改所需的值,然后保存(调用时是否覆盖原始文件)。对于嵌套输入,您必须具有嵌套字典。 loaded参数对于产生所需的格式(流样式)是必需的,否则对于嵌套集合,它将产生块样式:

default_flow_style=False

干杯!

稍后修改

正如Anthon所指出的,我的回答有一些缺陷。

  • 最好使用A: a B: {C: c, D: d, E: e} 而不是safe_load,因为后者有潜在危险。

  • 输出需要一个指令结束指示符(开头三个破折号)。要附加它们,我们在load方法中使用explicit_start=True(实际上应该是dump)。

  • 如果要生成更好的输出(尽管它们在语义上相同),则可以使用safe_dump而不是ruamel.yaml

请参阅Anthon的答案以获取更详细的信息,因为他是该软件包的作者。

答案 1 :(得分:2)

如果您阅读了PyYAML文档,将会发现它 告诉您使用load()函数具有潜在的危险, 所以要做的第一件事(因为你,几乎其他所有人都没有 需要它),而不是使用它,而是使用safe_load()

您还应该将输入文件更改为config.yaml, 自2006年以来,用于.yaml的YAML文件recommended extension

知道了,使用PyYAML更改config.yaml文件的方法:

import yaml

with open('config.yaml') as stream:
   data = yaml.safe_load(stream)

test = data['test']
test.update(dict(name="Tom", age="10", version="2.2"))

with open('output.yaml', 'wb') as stream:
   yaml.safe_dump(data, stream, default_flow_style=False, 
                  explicit_start=True, allow_unicode=True, encoding='utf-8')

这将为您提供一个output.yaml,其外观如下:

---
test:
  age: '10'
  name: Tom
  version: '2.2'

default_flow_style参数是必需的,这样才能不获取JSON之类的信息 叶节点映射的结构。 explicit_start获取 前导指标结束指示符(---),建议您始终使用 allow_unicode=True, encoding='utf-8'(并以二进制文件打开文件) 为了避免在您更改name时遇到意外或问题 到Björk Guðmundsdóttir

现在,您将注意到,这不会生成您想要的输出 (尽管在语义上是相同的):

  • 在可以解释为数字的字符串周围使用单引号而不是双引号
  • Tom周围没有双引号
  • 映射键的排序

如果YAML文件中有任何注释,这些注释将丢失。

更新YAML文件的更好方法是使用ruamel.yaml (免责声明:我是该软件包的作者),其中还有更多内容 没有PyYAML的默认值,处理YAML 1.2且不删除注释 (如果您将它们保存在文件中):

import ruamel.yaml


yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
yaml.explicit_start = True

with open('config.yaml') as stream:
   data = yaml.load(stream)

test = data['test']
test.update(dict(name="Tom", age="10", version="2.2"))

with open('output.yaml', 'wb') as stream:
    yaml.dump(data, stream)

您的输出文件将是:

---
test:
  name: "Tom"
  age: "10"
  version: "2.2"

这正是您想要的。