私はsome.yaml
以下の内容のファイル。
init_config: {}
instances:
- Host: <IP>
username: <username>
password: <password>
Yamlファイルは、以下のように解析および更新する必要があります。
init_config: {}
instances:
- Host: 1.2.3.4
username: Username
password: Password
値を解析して適切に更新するにはどうすればよいですか?
ruamel.yaml パッケージは、この種のラウンドトリップ、プログラムによる更新を行うために(PyYAMLから始めて)特に強化されました。
で始まる場合(余分な初期スペースを削除したことに注意してください):
init_config: {}
instances:
- Host: <IP> # update with IP
username: <username> # update with user name
password: <password> # update with password
そして実行:
import ruamel.yaml
file_name = 'input.yaml'
config, ind, bsi = ruamel.yaml.util.load_yaml_guess_indent(open(file_name))
instances = config['instances']
instances[0]['Host'] = '1.2.3.4'
instances[0]['username'] = 'Username'
instances[0]['password'] = 'Password'
with open('output.yaml', 'w') as fp:
yaml.dump(config, fp)
出力は次のようになります。
init_config: {}
instances:
- Host: 1.2.3.4 # update with IP
username: Username # update with user name
password: Password # update with password
マッピングキーの順序(Host
、username
およびpassword
)、スタイル、およびコメントそれ以上の特定のアクションなしで保存されます。
インデントとブロックシーケンスのインデントを推測する代わりに、手動で従来のロードを実行し、インデント値を自分で設定できます。
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=6, sequence=4)
with open(file_name) as fp:
config = yaml.load(fp)
この回答の履歴を見ると、より制限されたPyYAMLのようなAPIでこれを行う方法がわかります。
これは、上記のファイルから読み取り、必要に応じて解析および更新する方法です。
import yaml
fname = "some.yaml"
stream = open(fname, 'r')
data = yaml.load(stream)
data['instances'][0]['Host'] = '1.2.3.4'
data['instances'][0]['username'] = 'Username'
data['instances'][0]['password'] = 'Password'
with open(fname, 'w') as yaml_file:
yaml_file.write( yaml.dump(data, default_flow_style=False))
YAMLが必要かどうかわかりません。 YAMLタグの使用は別として、YAMLドキュメントには関心がないようです。それでは、なぜJinja2またはテンプレート言語を使用しないのでしょうか?
from jinja2 import Template
tmpl = Template(u'''\
init_config: {}
instances:
- Host: {{ IP }}
username: {{ username }}
password: {{ password }}
''')
print tmpl.render(
IP=u"1.2.3.4",
username=u"Username",
password=u"Password"
)
良いアイデアかどうかはわかりませんが、一部のフィールドが変更されたファイルを取得するだけであれば、YAMLドキュメントを実際に解析する必要はなく、テンプレート言語を直接利用できます。
ボーナス:ユースケース
タグが不明な非常に複雑なYAMLドキュメントを扱ってきました
...
propertiesIDs: { 1, 2, 3, 4 }
globalID: !myapplication.InterfaceID &primitiveID
replication: !myapplication.replication
beginDate: 2012-09-10T20:00:03
endDate: 2020-09-10T20:00:04
replicant_uuid:
? 17169504-B6AB-11E4-8437-36E258BB2172
? 206B5842-B6AB-11E4-AAC3-36E258BB2172
...
このドキュメントの有効な解析を実行することは難しく、時間がかかります。いくつかの値を設定するだけで、YAMLがサードパーティアプリケーションに送信されます。そのため、YAMLを解析したり、pyyamlを使用して有効なドキュメントを直接生成しようとする代わりに、テンプレートを使用して直接生成する方が簡単です(時間効率が高く、バグが発生しにくい)。さらに、テンプレート言語をループで簡単に使用して、動的にサイズ設定されたフィールドを設定できます。
開発者、プロダクション、ステージなどのドッカークレーンテンプレートを生成する方法は次のとおりです。
--- crane_gen.py ---
#!/usr/bin/env python
from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('crane_templates', './'))
tmpl = env.get_template('crane.yaml.tmpl')
result = tmpl.render(
IP=u"1.2.3.4",
username=u"Username",
password=u"Password"
)
5. python crane_gen.py> result.yaml
@MariusSiuramに触発された回答
以下は、PyYaml
を使用したサンプルです。私が理解しているように、あなたはyaml
形式のテンプレートのようなものを持っているので、山括弧内の場所を実際の値に置き換える必要があります。
import yaml
s = """
init_config: {}
instances:
- Host: <IP>
username: <username>
password: <password>
"""
dict_obj = yaml.load(s) # loads string in internal data structure - dict
dict_obj['instances'][0]['Host'] = 'localhost' # change values
print yaml.dump(dict_obj) # dumps dict to yaml format back