如何使用python更新yaml文件

时间:2015-02-17 08:28:50

标签: python pyyaml

我有一个some.yaml文件,其中包含以下内容。

    init_config: {}
    instances:
        - host: <IP>
          username: <username>
          password: <password>

应该解析和更新yaml文件,如下所示。

    init_config: {}
    instances:
        - host: 1.2.3.4
          username: Username
          password: Password

如何解析值并适当更新它们?

5 个答案:

答案 0 :(得分:17)

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.yml'
config, ind, bsi = 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.yml', '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

映射密钥(hostusernamepassword),样式和评论的顺序将保留,无需任何进一步的具体操作。

您可以执行手动传统加载,并自行设置缩进值,而不是使用缩进和块序列缩进猜测:

yaml = ruamel.yaml.YAML()
yaml.indent(mapping=6, sequence=4)
with open(file_name) as fp:
    config = yaml.load(open(file_name))

如果你看看这个答案的历史,你可以看到如何使用更有限的PyYAML之类的API来做到这一点。

答案 1 :(得分:8)

这是我可以从上面提到的文件中读取的内容,根据需要进行解析和更新。

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))

答案 2 :(得分:4)

我不知道你是否需要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发送到第三方应用程序。因此,不是直接使用pyyaml解析YAML或尝试生成有效文档,而是通过模板直接生成它更简单(更节省时间,更不容易出错)。此外,模板语言可以很容易地与循环一起使用来填充动态大小的字段。

答案 3 :(得分:1)

以下是我为开发,制作,舞台等制作码头起重机模板的方法......

  1. mkdir crane_templates
  2. 触摸crane_templates / init .py
  3. 使用nano crane_templates / some.yaml
  4. 添加模板内容
  5. Nano crane_gen.py
  6. --- 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&gt; result.yaml

    受@MariusSiuram启发的答案

答案 4 :(得分:0)

以下是使用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