ruamel.yaml中CommentedMap元素排序及通用排序方案实现问题
YAML文件加载后通用排序导出实现方案
需求说明
需要实现加载YAML文件后按指定规则排序再导出的功能,原有仅能针对devices数组的hostName字段排序的逻辑需要改造为通用能力。
原有示例YAML内容
devices: #list of devices #list of devices - hostName: testhb200 hostNetwork: 192.178.101.0 hostMask: 255.255.255.255 - hostName: testha100 hostNetwork: 192.178.225.12 hostMask: 255.255.255.252 hostGateway: 192.178.225.13 hostIp: 192.168.225.14 vendor: vendor model: qfx5200-
原有YAML工具类实现
# YAML settings class YamlUtil: logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO")) # YAML settings _yaml = YAML(typ="rt") _yaml.default_flow_style = False _yaml.explicit_start = False _yaml.preserve_quotes = True _yaml.indent(mapping=2, sequence=4, offset=2) _yaml.Representer.add_representer(OrderedDict, _yaml.Representer.represent_dict) def __init__(self, yaml: YAML = _yaml): # Override default class yaml settings self.yaml = yaml def load_file(self, file): with open(file, "r") as f: return self.yaml.load(f) def dump_file(self, data, file): with open(file, "w") as f: self.yaml.dump(data, f)
原有固定排序逻辑
yml = YamlUtil().load_file(args.input) yml['devices'].sort(lambda x: x['hostName']) YamlUtil().dump_file(yml, args.output)
通用排序改造方案
在原有YamlUtil类中新增通用排序方法,支持指定任意层级的数组路径、自定义排序规则、升降序配置:
from typing import List, Any, Callable, Optional class YamlUtil: # 原有代码保持不变,新增以下方法 def sort_sequence(self, data: dict, key_path: List[str], sort_key: Optional[Callable] = None, reverse: bool = False) -> dict: """ 对YAML数据中指定路径下的数组进行排序 :param data: 加载后的YAML数据对象 :param key_path: 要排序的数组所在的键路径,比如要排序根节点下的devices就传['devices'] :param sort_key: 排序用的key函数,和Python内置sort的key参数用法一致 :param reverse: 是否降序,默认False为升序 :return: 排序后的数据对象 """ # 逐层定位到要排序的数组对象 current = data for key in key_path: if key not in current: raise KeyError(f"指定的路径{key_path}在数据中不存在,异常位置:{key}") current = current[key] if not isinstance(current, list): raise TypeError(f"指定路径{key_path}对应的内容不是数组,无法排序") # 执行排序 current.sort(key=sort_key, reverse=reverse) return data
通用方法使用示例
原有按hostName升序排序场景
yml_util = YamlUtil() yml_data = yml_util.load_file(args.input) yml_util.sort_sequence(yml_data, key_path=['devices'], sort_key=lambda x: x['hostName']) yml_util.dump_file(yml_data, args.output)
拓展场景:按hostIp降序排序
yml_util = YamlUtil() yml_data = yml_util.load_file(args.input) yml_util.sort_sequence(yml_data, key_path=['devices'], sort_key=lambda x: x['hostIp'], reverse=True) yml_util.dump_file(yml_data, args.output)
注意事项
基于ruamel.yaml的rt(往返)模式实现,排序操作不会破坏原有YAML文件的注释、缩进、引号等格式配置,和原有逻辑完全兼容。
内容的提问来源于stack exchange,提问作者senthilkumar S
相关产品推荐
相关产品推荐

