python - 如何在Python中重置字典中的值?

标签 python yaml pyyaml

我有一个 YAML 文件,由于包含密码和敏感信息,因此无法提交到我的存储库。它看起来像这样:

devops:
  branch: somebranch

password:
  provider:
    digital_ocean:
      token:
        ""
    aws:
      bob:
        access_key_id:
          "XXX"
        secret_access_key:
          "XXX"
      jim:
        access_key_id:
          "XXX"
        secret_access_key:
          "XXX"
  dev:
    bob:
      "secret"
    jim:
      "another secret"
  app:
    mom:
      zookeeper:
        "XXX"
      admin:
        "XXX"

我正在尝试用Python开发一个脚本,以便我可以清除我的文件中的所有密码。我可以将其提交到我的存储库中,处理后它应该如下所示:

devops:
  branch: somebranch

password:
  provider:
    digital_ocean:
      token:
        ""
    aws:
      bob:
        access_key_id:
          ""
        secret_access_key:
          ""
      jim:
        access_key_id:
          ""
        secret_access_key:
          ""
  dev:
    bob:
      ""
    jim:
      ""
  app:
    mom:
      zookeeper:
        ""
      admin:
        ""

我知道可以将值设置到字典中,如下所示:

import os
import yaml

with open(os.environ['DEVOPS_HOME'] + "/vagrant/server/settings.yml") as f:
    settings = yaml.load(f)

for key in settings.keys():
    settings[key]=0

但是,这是我的输出:

{'password': 0, 'devops': 0}

有没有办法迭代我的字典并仅为我的密码设置值?或者我应该更改 YAML 文件的结构?

最佳答案

需要“删除”的键的命名似乎没有规律,但它们似乎有一个共同点,那就是它们都是键密码下的叶值。这使得递归成为一种选项,可以在不指定每个完整 key 路径的情况下删除所有它们:

import sys
import ruamel.yaml

yaml_str = """\
nas:
devops:
  branch: somebranch

password:
  provider:
    digital_ocean:
      token:
        ""
    aws:
      bob:
        access_key_id:
          "XXX"
        secret_access_key:
          "XXX"
      jim:
        access_key_id:
          "XXX"
        secret_access_key:
          "XXX"
  dev:
    bob:
      "secret"
    jim:
      "another secret"
  app:
    mom:
      zookeeper:
        "XXX"
      admin:
        "XXX"
"""

def wipe_pass(data, key):
    """wipe the value if it is a string instance"""
    if isinstance(data[key], type("")):
        data[key] = ruamel.yaml.scalarstring.DoubleQuotedScalarString("")
        return
    if isinstance(data[key], dict):
        for k in data[key]:
            wipe_pass(data[key], k)
        return
    raise NotImplementedError   # e.g. a YAML sequence

data = ruamel.yaml.round_trip_load(yaml_str, preserve_quotes=True)
wipe_pass(data, 'password')
ruamel.yaml.round_trip_dump(data, sys.stdout)

给出:

devops:
  branch: somebranch

password:
  provider:
    digital_ocean:
      token: ""
    aws:
      bob:
        access_key_id: ""
        secret_access_key: ""
      jim:
        access_key_id: ""
        secret_access_key: ""
  dev:
    bob: ""
    jim: ""
  app:
    mom:
      zookeeper: ""
      admin: ""

请注意,您的原始 YAML 的键值对格式不一致,其中值不是映射。这里的输出与您的原始 branch: somebranch 对一致。

ruamel.yaml.scalarstring.DoubleQuotedScalarString("") 是获取 "" 作为输出所必需的。如果您只分配 "",您将在 YAML 文件中为空字符串获得默认的 '' 单引号。

您可以尝试使用 PyYAML 执行上述操作,但您将丢失所有注释、不受保证的键顺序、丢失 password: 之前的空行以及可能更多。这使得它在很大程度上无法用于往返数据(加载、修改、转储),这些数据在提交之间必须具有最小的更改。

<小时/>

¹ 这是使用 ruamel.yaml 完成的一个 YAML 1.2 解析器,我是其作者。

关于python - 如何在Python中重置字典中的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40280497/

相关文章:

python - 从 Pandas 中的所有列值中去除空间

Python - 项目列表中的多个替换组合

java - SnakeYaml错误: No writable property on class

variables - Docker Compose 中的环境变量赋值 - 冒号方式

ruby - YAML::dump 中的 ArgumentError 如果(看起来像一个)日期无效

python - 将 YAML 中的 block 格式和流格式与 Python 混合使用

python - 计算列表中元素出现次数的 pythonic 方法是什么?

python - 通过与 Pandas 中的另一个数据框匹配来替换列表列的有效方法

python - PyYAML yaml.dump() 为字符串键 > 122 个字符生成复杂键?

json - 何时使用 YAML 而不是 JSON