如何在 python3 中使用 yaml 转储保留格式

How to preserve format with yaml dump in python3

我只想从以下带有 python.

的 yaml 文件中更改属性 anotherName

test.yaml:

---
kind: test
scope: not far
spec:
  test1:
    options:
      - name: test.com
        anotherName: example.com
        empty: []
    groupOne: []
    emptyList:
      firstList: []
      secondList: []

代码(基于this answer

import yaml
with open("test.yaml", 'r') as stream:
    try:
        loaded=yaml.safe_load(stream)
    except yaml.YAMLError as exc:
        print(exc)
    temp= loaded['spec']['test1']['options']
    for elem in temp:
        elem['anotherName']='somethingChanged'
with open("modified.yaml", 'w') as stream:
    try:
        yaml.dump(loaded, stream)
        print(loaded)
    except yaml.YAMLError as exc:
        print(exc)

值已更改,但代码更改了 modified.yaml 的顺序和结构:

#First it misses the thre dashes
kind: test
scope: not far
spec:
  test1:
    emptyList:
      firstList: []
      secondList: []
    groupOne: []
    options:
    - anotherName: somethingChanged #then the order is changed
      empty: []
      name: test.com

您可能无法强制从 pyyaml 输出特定的输出,但如果您有这样一个特定的要求,您想要替换什么,那么为什么要从根本上解析 yml 的额外麻烦。如何将文件读入字符串然后进行替换:

import re
# Here you would need to read the file content. I define it here
content="""
---
kind: test
scope: not far
spec:
  test1:
    options:
      - name: test.com
        anotherName: example.com
        empty: []
    groupOne: []
    emptyList:
      firstList: []
      secondList: []
"""
print(re.sub(r'anotherName: [^\n]*', 'anotherName: somethingChanged', content))

输出:

---
kind: test
scope: not far
spec:
  test1:
    options:
      - name: test.com
        anotherName: somethingChanged
        empty: []
    groupOne: []
    emptyList:
      firstList: []
      secondList: []

如果您的 PyYAML 版本高于 5.1,您可以使用 sort_keys 参数来保留顺序。唯一需要更改的行是这一行:

yaml.dump(loaded, stream, sort_keys=False)