如何使用python更新yaml文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28557626/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 03:26:15  来源:igfitidea点击:

How to update yaml file using python

pythonpyyaml

提问by Chetan

I have a some.yamlfile with the below contents.

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

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

The yaml file should be parsed and updated as below.

yaml 文件应该被解析和更新如下。

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

How do I parse the values and update them appropriately?

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

采纳答案by Anthon

The ruamel.yamlpackage was specifically enhanced (by me starting from PyYAML) to do this kind of round-trip, programmatic, updating.

ruamel.yaml包是专门(由我从PyYAML开始)做这种往返,编程,更新的增强。

If you start with (please note I removed the extra initial spaces):

如果你开始(请注意我删除了额外的初始空格):

init_config: {}
instances:
    - host: <IP>              # update with IP
      username: <username>    # update with user name
      password: <password>    # update with password

and run:

并运行:

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)

The output will be:

输出将是:

init_config: {}
instances:
    - host: 1.2.3.4           # update with IP
      username: Username      # update with user name
      password: Password      # update with password

The ordering of mapping keys (host, usernameand password), the style and the commentsare preserved without any further specific action.

映射键(hostusernamepassword)、样式和注释的顺序被保留,无需任何进一步的特定操作。

Instead of having the indent and block sequence indent guessed, you can do a manual traditional load, and set the indent values yourself:

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

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


If you look at the history of this answer, you can see how to do this with a more limited, PyYAML like, API.

如果您查看此答案的历史记录,您可以了解如何使用更有限的 PyYAML 之类的 API 来执行此操作。

回答by Deck

Here are sample using PyYaml. As I understand you have something like template in yamlformat, and you have to substitute places in angle brackets with actual values.

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

回答by Chetan

This is how i can read from the above file i mentioned, parse and update as needed.

这就是我如何从我提到的上述文件中读取,根据需要解析和更新。

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

回答by MariusSiuram

I don't know if you need YAML. Aside from using the YAML tag, it seems that you have no interest in the YAML document. So why not using Jinja2 or some template language?

我不知道你是否需要 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"
)

I don't know if it is a good idea, but if you only need to obtain a file with some fields changed, you don't need to actually parse the YAML document and can benefit from a Template language directly.

我不知道这是否是一个好主意,但是如果您只需要获取更改了某些字段的文件,则您不需要实际解析 YAML 文档,可以直接从模板语言中受益。



Bonus:Use case

奖励:用例

I have worked with very complex YAML documents, for which there are tags unknown

我处理过非常复杂的 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
...

Performing a valid parse of this document is difficult and time-consuming. I only need to populate some values, and the YAML is sent to a third-party application. So instead of parsing the YAML or trying to generate a valid document directly using pyyaml, is simpler (more time-efficient, less bug-prone) to generate it directly through templates. Moreover, template languages can easily be used with loops to populate dynamically sized fields.

执行此文档的有效解析既困难又耗时。我只需要填充一些值,并将 YAML 发送到第三方应用程序。因此,与其解析 YAML 或尝试直接使用 pyyaml 生成有效文档,不如直接通过模板生成它更简单(更省时,更不容易出错)。此外,模板语言可以很容易地与循环一起使用来填充动态大小的字段。

回答by Kostyantyn

Here's how i generate docker-crane templates for dev, production, stage, etc...

这是我为开发、生产、阶段等生成 docker-crane 模板的方法......

  1. mkdir crane_templates
  2. touch crane_templates/init.py
  3. Add template content with nano crane_templates/some.yaml
  4. Nano crane_gen.py
  1. mkdir起重机模板
  2. 触摸起重机模板/ init.py
  3. 使用 nanocracker_templates/some.yaml 添加模板内容
  4. 纳米起重机_gen.py

--- crane_gen.py ---

---起重机_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

5. python起重机_gen.py > result.yaml

Answer inspired by @MariusSiuram

答案灵感来自@MariusSiuram