【问题标题】:Python update YAML without changing formattingPython 更新 YAML 而不更改格式
【发布时间】:2021-10-01 18:26:12
【问题描述】:

我想更新 yaml 文件中的特定属性,而其余部分保持不变,包括格式化、cmets 等。我正在使用 raumel.yaml。但是当我保存文件时,它的格式会变得混乱。我正在使用 python 3.9.5 和 raumel.yaml 版本:0.17.10。

test.yaml:

sso:
  version: 1.0.0
  configs:
  - configName: config1.conf
    fileContent: 'startDelaySeconds: 0

      lowercaseOutputName: true

      lowercaseOutputLabelNames: false

      whitelistObjectNames: [''org.apache.commons.pool2:*'']

      blacklistObjectNames: []

      rules:

      - pattern: ".*"

      '

我更新版本:

from ruamel.yaml import YAML
yaml = YAML()
with open('test.yaml') as f:
    test = yaml.load(f)
test['sso']['version'] = '1.0.1'
with open('test2.yaml', 'w') as f:
    yaml.dump(test, f)

但是保存文件的fileContent 的格式发生了变化(换行符替换为\n 等)。 test2.yaml:

sso:
  version: 1.0.1
  configs:
  - configName: config1.conf
    fileContent: "startDelaySeconds: 0\nlowercaseOutputName: true\nlowercaseOutputLabelNames:\
      \ false\nwhitelistObjectNames: ['org.apache.commons.pool2:*']\nblacklistObjectNames:\
      \ []\nrules:\n- pattern: \".*\"\n"

【问题讨论】:

  • 我更新了您的程序,因为您在此处粘贴的内容永远无法提供该输出。
  • @Anthon 谢谢,我复制了错误的命令

标签: python yaml ruamel.yaml


【解决方案1】:

您可能错过的是值中的引号 因为您的输出从单引号变为双引号。默认ruamel.yaml 不尝试保留引号,从而能够删除任何多余的 引号,或者在这种情况下使用更紧凑的表示。 在标量中使用不需要单引号的双引号 被复制。

您可以通过设置.preserve_quotes 属性来保留引号:

import sys
from ruamel.yaml import YAML

yaml = YAML()
yaml.preserve_quotes = True
with open('test.yaml') as f:
    test = yaml.load(f)
test['sso']['version'] = '1.0.1'
yaml.dump(test, sys.stdout)

给出:

sso:
  version: 1.0.1
  configs:
  - configName: config1.conf
    fileContent: 'startDelaySeconds: 0

      lowercaseOutputName: true

      lowercaseOutputLabelNames: false

      whitelistObjectNames: [''org.apache.commons.pool2:*'']

      blacklistObjectNames: []

      rules:

      - pattern: ".*"

      '

我建议考虑对值使用文字样式标量 包含换行符的,因为你不需要加倍换行符, 也不需要在标量中加双引号:

yaml_str = """
sso:
  version: 1.0.0
  configs:
  - configName: config1.conf
    fileContent: |
      startDelaySeconds: 0
      lowercaseOutputName: true
      lowercaseOutputLabelNames: false
      whitelistObjectNames: ['org.apache.commons.pool2:*']
      blacklistObjectNames: []
      rules:
      - pattern: ".*"
  
"""

import sys
from ruamel.yaml import YAML

yaml = YAML()
yaml.preserve_quotes = True
with open('test.yaml') as f:
    test = yaml.load(f)

data = yaml.load(yaml_str)
assert data['sso']['configs'][0]['fileContent']  == test['sso']['configs'][0]['fileContent']

【讨论】:

  • 谢谢,已经做到了,所以我接受了你的回答。还有一个问题:有没有办法保持缩进?特别是一些属性有更多的缩进,正在被删除。理想情况下不应该是这样,但这是很多人使用的共享配置文件,所以我不想弄乱其他人的东西。
  • 您不能单独保存它。您可以使用yaml.indent(6, 4, 2) 使映射缩进 6 个位置,并使用序列指示符 (-) 对 4 个位置进行序列化,从而在这 4 个位置偏移两个位置。你玩过吗?
  • 不幸的是,这不起作用,文件中有不同的缩进样式。如果我先尝试将缩进统一起来,可能会更容易。
猜你喜欢
  • 1970-01-01
  • 2021-07-07
  • 2015-07-09
  • 1970-01-01
  • 2022-01-23
  • 2019-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多