python合并复杂的YAML

标签 python yaml

我有一些 YAML 示例,如下所示:

type:
  - name: foo
    location: bar
releases:
- name: app1
  sha1: 11b318d4ec9f0baf75d8afc6f78cf66f955d459f
  url: https://url.com/app.tar.gz
- name: app2
  sha1: ef97bfaff05989ab006e88d28763feb8fbb32d45
  url: https://url.com/app2.tar.gz
jobs:
- instances: 1
  name: appname
  templates:
  - name: postgres
    release: 1.0

我想合并到一个 YAML 文件中,添加到看起来像这样的文件中

releases:
- name: app3
  sha1: ef97bfaff05989ab006e88d28763feb8fbb32d45
  url: https://url.com/app3.tar.gz
jobs:
-
  templates:
  - name: mysql
    release: 1.0

我尝试将它们转换为 dict,然后将它们合并在一起,但这根本不起作用。

结尾应该是这样的

type:
  - name: foo
    location: bar
releases:
- name: app1
  sha1: 11b318d4ec9f0baf75d8afc6f78cf66f955d459f
  url: https://url.com/app.tar.gz
- name: app2
  sha1: ef97bfaff05989ab006e88d28763feb8fbb32d45
  url: https://url.com/app2.tar.gz
- name: app3
  sha1: ef97bfaff05989ab006e88d28763feb8fbb32d45
  url: https://url.com/app3.tar.gz
jobs:
- instances: 1
  name: appname
  templates:
  - name: postgres
    release: 1.0
  - name: mysql
    release: 1.0

这就是我得到的dict:

{'jobs': [{'instances': 1,
           'name': 'appname',
           'templates': [{'name': 'postgres', 'release': 1.0}]},
          {'templates': [{'name': 'mysql', 'release': 1.0}]}],
 'releases': [{'name': 'app1',
               'sha1': '11b318d4ec9f0baf75d8afc6f78cf66f955d459f',
               'url': 'https://url.com/app.tar.gz'},
              {'name': 'app2',
               'sha1': 'ef97bfaff05989ab006e88d28763feb8fbb32d45',
               'url': 'https://url.com/app2.tar.gz'},
              {'name': 'app3',
               'sha1': 'ef97bfaff05989ab006e88d28763feb8fbb32d45',
               'url': 'https://url.com/app3.tar.gz'}],
 'type': [{'location': 'bar', 'name': 'foo'}]}

如果您注意到我的 mysql 模板不在 postgres 模板列表中,而是在另一个 dict 中。

最佳答案

我会选择递归扩展。如果您使用 PyYaml 将第一个文件和第二个文件读取到不同的词典中,则可以尝试以下操作:

def extend_dict(extend_me, extend_by):
    if isinstance(extend_by, dict):
        for k, v in extend_by.iteritems():
            if k in extend_me:
                extend_dict(extend_me.get(k), v)
            else:
                extend_me[k] = v
    else:
        extend_me += extend_by

extend_dict(file1, file2)

合并的结果将在file1 字典中。

更新:

我添加了一些内容。它看起来有点乱,但我认为您可以在 EXTENDABLE_KEYS 中添加您想要扩展的键。

使用正确的 YAML 文件对其进行测试,让我知道它是否正常工作。

EXTENDABLE_KEYS = ('templates', )


def extend_dict(extend_me, extend_by):
    if isinstance(extend_me, dict):
        for k, v in extend_by.iteritems():
            if k in extend_me:
                extend_dict(extend_me[k], v)
            else:
                extend_me[k] = v
    else:
        if isinstance(extend_me, list):
            extend_list(extend_me, extend_by)
        else:
            extend_me += extend_by


def extend_list(extend_me, extend_by):
    missing = []
    for item1 in extend_me:
        if not isinstance(item1, dict):
            continue

        for item2 in extend_by:
            if not isinstance(item2, dict) or item2 in missing:
                continue

            # Check if any key is an extendable key
            if filter(lambda x: x in EXTENDABLE_KEYS, item1.keys()):
                extend_dict(item1, item2)
            else:
                missing += [item2, ]
    extend_me += missing


extend_dict(file1, file2)

print yaml.dump(file1, default_flow_style=False)

通过该代码段,我获得了以下内容:

type:
- location: bar
  name: foo
releases:
- name: app1
  sha1: 11b318d4ec9f0baf75d8afc6f78cf66f955d459f
  url: https://url.com/app.tar.gz
- name: app2
  sha1: ef97bfaff05989ab006e88d28763feb8fbb32d45
  url: https://url.com/app2.tar.gz
- name: app3
  sha1: ef97bfaff05989ab006e88d28763feb8fbb32d45
  url: https://url.com/app3.tar.gz
jobs:
- instances: 1
  name: appname
  templates:
  - name: postgres
    release: 1.0
  - name: mysql
    release: 1.0

关于python合并复杂的YAML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36584338/

相关文章:

python - 如何在Python中重置字典中的值?

java - SnakeYaml dump函数用单引号写入

c++ - 如何在静态库中提供默认的 YAML 配置值?

python - urllib2/httplib 如何通过 Squid 代理与 HTTP 1.1 进行 HTTPS 连接?

python - Tornado -redis : LPOP works but BLPOP doesn't?

python - 在 Python 3 中检查多个整数

javascript - 最不同的数据交换格式?

python - KafkaProducer for Python 如果在命令行上完成则发送消息,但如果通过 Python 脚本完成则不会发送消息

python - 语法无效(For 循环括号/圆括号)

python - 如何以人类可读的格式写入yaml文件?