如何使用来自另一个字典中匹配键的值更新YAML文件?

时间:2018-04-17 21:21:37

标签: python dictionary yaml pyyaml ruamel.yaml

我有一个名为input.yaml的YAML文件:

---
'001':
  name: Ben
  email: ben@test.com
'002':
  name: Lisa
  email: lisa@test.com
'003':
  name: Alex
  email: alex@test.com
.
.
.

我有一本字典:

my_dict = {'001': '000-111-2222', '002': '000-111-2223', '003': '000-111-2224', ...}

我希望有一个名为output.yaml的更新文件,如下所示:

---
'001':
  name: Ben
  email: ben@test.com
  phone: 000-111-2222
'002':
  name: Lisa
  email: lisa@test.com
  phone: 000-111-2223
'003':
  name: Alex
  email: alex@test.com
  phone: 000-111-2224
.
.
.

请注意输出文件如何添加“phone”字段,其中的值来自匹配键的字典值。

我如何获得此类文件? ......我尝试过各种各样的事。

2 个答案:

答案 0 :(得分:2)

如果您担心文件的格式保持不变(如果有评论表明它们应该保留),您可以这样做:

import ruamel.yaml

yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
yaml.explicit_start = True

with open('input.yaml') as fp:
    data = yaml.load(fp)

my_dict = {
    '001': '000-111-2222',
    '002': '000-111-2223',
    '003': '000-111-2224',
}

for k in my_dict:
    data.setdefault(k, {})['phone'] = my_dict[k]

with open('output.yaml', 'w') as fp:
    yaml.dump(data, fp)

之后output.yaml包含:

---
'001':
  name: Ben
  email: ben@test.com
  phone: 000-111-2222
'002':
  name: Lisa
  email: lisa@test.com
  phone: 000-111-2223
'003':
  name: Alex
  email: alex@test.com
  phone: 000-111-2224

注意:

  1. yaml.preserve_quotes = True并不是必需的,因为需要引号的标量(您的字符串从零开始)单引号是默认值,输入中也没有多余的引号。

  2. 我使用data.setdefault(k, {})['phone']而不是检查@Aaron在其来源中建议的data[k]是否存在。如果密钥k不在data中,它将创建一个(空)字典。

  3. 如果您只想更新匹配的键,请在for循环中使用以下内容:

    try:
        data[k]['phone'] = my_dict[k]
    except KeyError:
        pass
    
  4. 您需要yaml.explicit_start = True才能在文档开始时获取---ruamel.yaml不会自动保留该内容。如果您还需要文档结束标记(...),请使用:yaml.explicit_end = True

  5. 如果您希望电话号码显示在nameemail之间,请使用:

    data.setdefault(k, {}).insert(1, 'phone', my_dict[k])
    

    给出:

    ---
    '001':
      name: Ben
      phone: 000-111-2222
      email: ben@test.com
    '002':
      name: Lisa
      phone: 000-111-2223
      email: lisa@test.com
    '003':
      name: Alex
      phone: 000-111-2224
      email: alex@test.com
    

    (即0表示在第一个键之前插入,1在第二个键之前插入等。)

答案 1 :(得分:1)

除了阅读和阅读写入文件,也许这会指出你正确的方向:

import yaml


document = """
---
'001':
  name: Ben
  email: ben@test.com
'002':
  name: Lisa
  email: lisa@test.com
'003':
  name: Alex
  email: alex@test.com
"""

phones = {'001': '000-111-2222', '002': '000-111-2223', '003': '000-111-2224'}

doc = yaml.safe_load(document)

for k, v in phones.items():
    # Might want to check that 'doc[k]' exists
    doc[k]['phone'] = v

print(yaml.safe_dump(doc, default_flow_style=False, explicit_start=True))

输出:

'001':
  email: ben@test.com
  name: Ben
  phone: 000-111-2222
'002':
  email: lisa@test.com
  name: Lisa
  phone: 000-111-2223
'003':
  email: alex@test.com
  name: Alex
  phone: 000-111-2224