【问题标题】:How do I dump an OrderedDict out as a YAML file?如何将 OrderedDict 转储为 YAML 文件?
【发布时间】:2019-05-21 07:26:07
【问题描述】:

我编写了一个简单的脚本,最终使用 ruamel.yaml 将其发布到 YAML 文件中(示例如下所示)。我使用了collections.OrderedDict,这样我就可以按字母顺序对键进行重新排序,但是即使在使用json.load/json.dumps 重新排序并将其转换回字典之后,我也无法以有序的方式将其打印出来。

我了解 YAML 规范不关心顺序,但我个人希望 YAML 文件排序,使用 ruamel.yaml 模块的正确方法是什么?

logging.to_syslog: 'false'
statsbeat:
  multicast_interface_name: 'p1p1'
  primary_field_name: 'primary'
  udp_address: '239.253.0.50:20016'
  all_documents_index: 'statsall-${statsbeat.exchange_code}-${statsbeat.name}'
  exchange_code: 'd'
  primary_field_algorithm: 'range'
  cloud_type: 'none'
  primary_field_algorithm_range: '1-48'
  name: 'otpr'
logging.files:
  permissions: '0644'
  rotateeverybytes: 52428800
  keepfiles: 7
  name: '${statsbeat.name}.log'

【问题讨论】:

    标签: python yaml ruamel.yaml ordereddict


    【解决方案1】:

    当您以ruamel.yaml 的默认往返模式加载 YAML 文件时, 然后将一个序列加载到CommentedMap(定义在 ruamel.yaml.comments.py)。 CommentedMapOrderedDict(或 Python2 上的 ruamel.ordereddict)。

    因此,您可以做的一件事是将您的 OrderedDict 转换为 CommentedMap

    import sys
    import ruamel.yaml
    from ruamel.yaml.comments import CommentedMap
    from collections import OrderedDict
    
    data = OrderedDict([
      ('logging.to_syslog', 'false'),
      ('statsbeat', OrderedDict([
        ('multicast_interface_name',  'p1p1'),
        ('primary_field_name',  'primary'),
        ('udp_address',  '239.253.0.50:20016'),
        ('all_documents_index',  'statsall-${statsbeat.exchange_code}-${statsbeat.name}'),
        ('exchange_code',  'd'),
        ('primary_field_algorithm',  'range'),
        ('cloud_type',  'none'),
        ('primary_field_algorithm_range',  '1-48'),
        ('name',  'otpr'),
      ])),
      ('logging.files', OrderedDict([
        ('permissions',  '0644'),
        ('rotateeverybytes',  52428800),
        ('keepfiles',  7),
        ('name',  '${statsbeat.name}.log'),
      ])),
    ])
    
    def comseq(d):
        if isinstance(d, OrderedDict):
            cs = CommentedMap()
            for k, v in d.items():
                cs[k] = comseq(v)
            return cs
        return d
    
    
    data = comseq(data)
    
    
    yaml = ruamel.yaml.YAML()
    yaml.dump(data, sys.stdout)
    

    给出:

    logging.to_syslog: 'false'
    statsbeat:
      multicast_interface_name: p1p1
      primary_field_name: primary
      udp_address: 239.253.0.50:20016
      all_documents_index: statsall-${statsbeat.exchange_code}-${statsbeat.name}
      exchange_code: d
      primary_field_algorithm: range
      cloud_type: none
      primary_field_algorithm_range: 1-48
      name: otpr
    logging.files:
      permissions: '0644'
      rotateeverybytes: 52428800
      keepfiles: 7
      name: ${statsbeat.name}.log
    

    (如果你想要像你的例子中那样多余的单引号,你可以转换字符串 到SingleQuotedScalarString,从ruamel.yaml.scalarstring导入)。


    但可能更简单的方法是指示代表 以与 CommentedMap 相同的方式表示 OrderedDict。假设 data 的导入和定义和以前一样,你可以这样做:

    from ruamel.yaml.representer import RoundTripRepresenter
    
    class MyRepresenter(RoundTripRepresenter):
        pass
    
    ruamel.yaml.add_representer(OrderedDict, MyRepresenter.represent_dict, 
                                representer=MyRepresenter)
    
    yaml = ruamel.yaml.YAML()
    yaml.Representer = MyRepresenter
    
    yaml.dump(data, sys.stdout)
    

    结果与之前完全相同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-11
      • 2012-08-13
      • 1970-01-01
      • 2014-11-03
      • 1970-01-01
      • 1970-01-01
      • 2019-10-22
      • 1970-01-01
      相关资源
      最近更新 更多