我有这个示例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文件。
鉴于你使用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
的loaded
中,您可以修改所需的值然后保存它(覆盖原始文件或不覆盖您的调用)。对于嵌套输入,您必须有一个嵌套的dict,您必须修改它。 default_flow_style=False
参数是生成所需格式(流样式)所必需的,否则对于嵌套集合,它会生成块样式:
A: a
B: {C: c, D: d, E: e}
干杯!
稍后编辑:
正如安森指出的那样,我的答案有一些缺陷。
safe_load
而不是load
,因为后者有潜在危险。explicit_start=True
方法中使用dump
(实际上应该是safe_dump
)。ruamel.yaml
而不是yaml
请参阅Anthon的答案以获取更详细的信息,因为他是该软件包的作者。
如果你仔细阅读PyYAML文档,你会发现它告诉你使用load()
函数是有潜在危险的,所以首先要做的事情(因为你,而且几乎所有其他人都不需要它)都没有使用它,但使用safe_load()
代替。
您还应该将输入文件更改为config.yaml
,自2006年以来,YAML文件的recommended extension一直是.yaml
。
知道了,使用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"
这正是你想要的。