python3 - 在YAML文件中编辑值

时间:2017-01-19 09:39:09

标签: python yaml

我正在尝试使用PyYAML和Python3来编辑YAML文件中的值(它是一个Hiera数据结构,但这只是一点点。)

使用yaml.safe_loadyaml.dump很容易实现。我遇到的问题是我需要保留注释,空格,排序和其他格式。也就是说,当我编辑给定键的值时,应该是文件中的唯一更改。 (不需要自己添加或删除密钥。)

就我而言,这些是二级密钥。我可以使用正则表达式或某种形式的状态机来完成它 - 但它非常讨厌。是否有人知道图书馆已经整齐地做到了这一点?

这是有关YAML的一个愚蠢的例子:

---
# Some form of comment block.
# Some form of comment block.
# Some form of comment block.

# This is my config block.
config::me:
  key0: 123
  key1: 456

# This is another config block:
applications:
  frontend:
    version: '2.4.2'
    enabled: true
  backend:
    version: '4.3.9'
    enabled: false

# More comments etcetera.

基本上我需要做的是定位applications.frontent.version并将值从2.4.2更新为2.4.3,而不触及文件中的任何其他内容。

1 个答案:

答案 0 :(得分:0)

你可以使用ruamel.yaml作为PyYAML¹的衍生物。它特别创建用于执行这种往返,保留注释以及原始文件中的其他一些内容,大多数解析器在往返过程中丢弃(它也是YAML 1.2兼容,而PyYAML支持1.1)

import sys
import ruamel.yaml
from ruamel.yaml.util import load_yaml_guess_indent
from ruamel.yaml.scalarstring import SingleQuotedScalarString

ys = """\
---
# Some form of comment block.
# Some form of comment block.
# Some form of comment block.

# This is my config block.
config::me:
  key0: 123
  key1: 456

# This is another config block:
applications:
  frontend:
    version: '2.4.2'
    enabled: true
  backend:
    version: '4.3.9'
    enabled: false

# More comments etcetera.
"""

data, indent, block_seq_indent = load_yaml_guess_indent(ys, preserve_quotes=True)
data['applications']['frontend']['version'] = SingleQuotedScalarString('2.4.3')
ruamel.yaml.round_trip_dump(data, sys.stdout, explicit_start=True)

给你:

---
# Some form of comment block.
# Some form of comment block.
# Some form of comment block.

# This is my config block.
config::me:
  key0: 123
  key1: 456

# This is another config block:
applications:
  frontend:
    version: '2.4.3'
    enabled: true
  backend:
    version: '4.3.9'
    enabled: false

# More comments etcetera.

只有preserve_quotes选项和SingleQuotedScalarString()的使用才有必要,因为您在标量2.4.34.3.9周围都有引号,这些引号是多余的,通常会被删除。

¹免责声明:我是ruamel.yaml的作者。