Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Python中通过字典重置值?_Python_Yaml_Pyyaml - Fatal编程技术网

如何在Python中通过字典重置值?

如何在Python中通过字典重置值?,python,yaml,pyyaml,Python,Yaml,Pyyaml,我有一个YAML文件无法提交到我的存储库,因为它包含密码和合理的信息。看起来是这样的: devops: branch: somebranch password: provider: digital_ocean: token: "" aws: bob: access_key_id: "XXX" secret_access_key: "XXX" jim

我有一个
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"
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
如果我可以清除我文件中的所有密码,我将尝试在
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:
        ""
我知道可以在字典中设置如下值:

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"
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文件的结构?

您需要手动将密码部分中的每个字符串设置为空字符串。例如,如果您的字典如下所示:

{
    'public_stuff': 'this should not be changed',
    'password':
    {
        'category1':
         {
            'user': 'password'
         },
         'other_user': 'other_password',
    },
}
可以在清除所有字符串值的函数中递归地执行此操作。如果涉及到字典值,它将对该值本身执行函数

def clear_password(content):
    for key in content:
        if isinstance(content[key], str):
            content[key] = ""
        elif isinstance(content[key], dict):
            clear_password(content[key])

clear_password(settings["password"])

在Python 2中,
str
可能需要是
basestring
unicode
需要“擦除”值的键在命名上似乎没有规律性,但它们似乎有一个共同点,那就是它们都是键密码下的叶值。这使得递归成为一个选项,可以在不指定每个完整密钥路径的情况下将它们全部擦除

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的键值对格式不一致,其中值不是映射。这里的输出与原始的
分支:somebranch
对一致

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

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



这是使用YAML 1.2解析器完成的,我是该解析器的作者。

您可以只迭代密码部分的键吗?我正试图这样做@S.deMelo,但我不知道怎么做。我是Python新手。你能用一个例子告诉我怎么做吗?非常感谢@Anthon!我想你的意思是
wipe_pass
而不是
clean_pass
函数中的
wipe_pass
。@xZise是的,谢谢你指出。粘贴后,我重新命名了它,以确认我使用的评论术语。