2016-10-27 9 views
1

私はYAMLファイルを持っていますが、これはパスワードとわかりやすい情報が含まれているため、私のリポジトリにコミットできません。それは次のようになります。Pythonで辞書の値をリセットする方法は?

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ファイルの構造を変更する必要がありますか?

+1

パスワードセクションのキーのみを反復できますか? –

+0

私は@ S.deMeloをやろうとしていますが、どうしたらいいか分かりません。私はPythonが初めてです。あなたは私の例をどのようにしてくれますか? –

答えて

1

"ワイピング"が必要なキーの名前は規則的ではないようですが、共通点の1つは、キーパスワードの下にあるすべてのリーフ値です。すなわち、各全キーのパスを指定せずにそれらすべてを拭くために再帰]オプションになります¹:

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ペアと一致しています。

は、出力として""を得るために必要です。 ""を割り当てるだけであれば、YAMLファイルの空の文字列のデフォルト値は''となります。

PyYAMLを使って上記を行うことはできますが、コメントが失われ、キーの順序が保証されず、password:の前に空の行がなくなります。そのため、コミット間の変更を最小限に抑えなければならないデータのラウンドトリップ(ロード、変更、ダンプ)ではほとんど使用できなくなります。


は、これは私が著者だそのruamel.yaml YAML 1.2パーサを使用して行われたを¹しました。

+0

ありがとう@Anthon! –

+0

私はあなたが 'wipe_pass'関数の中で' clean_pass'の代わりに 'wipe_pass'を意味したと思います。 – xZise

+0

@xZiseはい、ありがとうございます。私が使用した解説用語を確認するために貼り付けた後、名前を変更しました。 – Anthon

1

パスワードセクションの各文字列を空の文字列に手動で設定する必要があります。たとえば、辞書が次のような場合:

これは、すべての文字列値を消去する関数で再帰的に行うことができます。ディクショナリ値の場合は、その値自体に対して関数を実行します。

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では、strbasestringまたはunicodeする必要があります。

関連する問題