如何使用 python 更新 yaml 文件
How to update yaml file using python
我有一个包含以下内容的 some.yaml
文件。
init_config: {}
instances:
- host: <IP>
username: <username>
password: <password>
yaml 文件应按如下方式解析和更新。
init_config: {}
instances:
- host: 1.2.3.4
username: Username
password: Password
如何解析值并适当地更新它们?
这里是使用 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
这就是我如何从我提到的上述文件中读取、解析和根据需要更新的方式。
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 生成有效文档,不如直接通过模板生成它更简单(更省时,更不容易出错)。此外,模板语言可以很容易地与循环一起使用来填充动态大小的字段。
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'
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=ind, sequence=ind, offset=bsi)
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。
以下是我如何为开发、生产、阶段等生成 docker-crane 模板...
- mkdir crane_templates
- touch crane_templates/init.py
- 用nano添加模板内容crane_templates/some.yaml
- 纳米crane_gen.py
--- 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
我有一个包含以下内容的 some.yaml
文件。
init_config: {}
instances:
- host: <IP>
username: <username>
password: <password>
yaml 文件应按如下方式解析和更新。
init_config: {}
instances:
- host: 1.2.3.4
username: Username
password: Password
如何解析值并适当地更新它们?
这里是使用 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
这就是我如何从我提到的上述文件中读取、解析和根据需要更新的方式。
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 生成有效文档,不如直接通过模板生成它更简单(更省时,更不容易出错)。此外,模板语言可以很容易地与循环一起使用来填充动态大小的字段。
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'
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=ind, sequence=ind, offset=bsi)
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。
以下是我如何为开发、生产、阶段等生成 docker-crane 模板...
- mkdir crane_templates
- touch crane_templates/init.py
- 用nano添加模板内容crane_templates/some.yaml
- 纳米crane_gen.py
--- 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