读取YAML文件并通过迭代部分,键和值来获取值

时间:2017-05-19 15:27:35

标签: python python-2.7 pyyaml

我能够迭代YAML配置文件并执行每个部分所需的所有操作。除了嵌套的for循环之外,有什么方法可以使用更加pythonic代码实现相同的结果吗?

import yaml
with open('/tmp/cfg_demo.yaml') as yfile:
    cfg = yaml.safe_load(yfile)

for header, subsections in cfg.iteritems():
    for section, key in subsections.iteritems():
        for values in key:
            for field, value in values.iteritems():
                if section == 'permission_assign':
                    # execute service to handle permissions
                    print section, field, value
                elif section == 'group_assign':
                    # execute service to handle group permissions
                    print section, field, value
                elif section == 'group_users_assign':
                    # execute service to handle user permissions
                    print section, field, value
                elif section == 'new_users':
                    # Execute service to handle user creation
                    print section, field, value

cfg_demo.yaml内容:

access_management:
  permission_assign:
    - sample_1: service:1
    - sample_2: service:2
  group_assign:
    - sample_1: Group_1
    - sample_2: Group_2
  group_users_assign:
    - Group_1: User_a User_b
  new_users:
    - User_a: user_pwd
    - User_b: user_pwd

输出:

permission_assign sample_1 service:1
permission_assign sample_2 service:2
group_assign sample_1 Group_1
group_assign sample_2 Group_2
group_users_assign Group_1 User_a User_b
new_users User_a user_pwd
new_users User_b user_pwd

1 个答案:

答案 0 :(得分:0)

由于键permission_assigngroup_assign等必然会比使用有序键值对信息打印更有用,我会根据这些信息创建不同类的对象。

from __future__ import print_function

from ruamel import yaml
from collections import OrderedDict


with open('cfg_demo.yml') as fp:
    cfg = yaml.safe_load(fp)


class SectionMap(dict):
    def add(self, cls):
        name = ''.join([n if n.islower() else '_' + n.lower() for n in cls.__name__])
        if name[0] == '_':
            name = name[1:]
        cls.name = name
        self[name] = cls

section_map = SectionMap()


class AssignedFieldValue:
    def __init__(self, args):
        self.values = OrderedDict()
        for x in args:
            for k in x:
                self.values[k] = x[k]

    def dump(self):
        for k in self.values:
            v = self.values[k]
            print(self.name, k, v)


class PermissionAssign(AssignedFieldValue):
    pass
section_map.add(PermissionAssign)


class GroupAssign(AssignedFieldValue):
    pass
section_map.add(GroupAssign)


class GroupUsersAssign(AssignedFieldValue):
    pass
section_map.add(GroupUsersAssign)


class NewUsers(AssignedFieldValue):
    pass
section_map.add(NewUsers)

for header in cfg:
    subsections = cfg[header]
    for section_name in subsections:
        section = section_map[section_name](subsections[section_name])
        section.dump()

这与您提供的输出打印相同,但循环更简单。

这样你就可以摆脱通过扩展类,然后添加特定的,真实的功能。只需将section.dump()替换为section.do(),并为每个do()子类实施方法AssignedFieldValue

如果您可以更改YAML,那么我会将其更改为包含标签:

access_management:
  - !permission_assign
    sample_1: service:1
    sample_2: service:2
  - !group_assign
    sample_1: Group_1
    sample_2: Group_2
  - !group_users_assign
    Group_1: User_a User_b
  - !new_users
    User_a: user_pwd
    User_b: user_pwd

基于适当的构造函数并使用round_trip_load()(保留键值对的顺序),您可以加载此YAML并直接生成节,而无需SectionMap()个东西。这更像是Pythonic,更好地利用了YAML功能。

请注意{3}在Python3中消失了,因此iteritems()作为声明。上面的代码将在Python 2和3中运行