如何自定义PyYaml Dumper实现按类型输出非嵌套集合?
自定义PyYAML Dumper实现指定格式输出
需求说明
需要导出如下格式的YAML文件:
Strings: - "A very very long string" - "A very very long string2" - "A very very long string3" - "A very very long string4" - "A very very long string5" - "A very very long string8" Numbers: [1,2,3,4,5,6,7,8,9] StringsDict: - First: "A very very long string" - Second: "A very very long string8" NumbersDict: {"First": 12, "Second": 156}
输出规则:
- 底层仅含数字的集合(列表/字典)以单行紧凑格式输出
- 底层包含字符串的集合(列表/字典)每个元素单独占一行
- 嵌套集合始终以单行紧凑格式输出
实现方案
通过继承PyYAML的Dumper类,重写列表和字典的表示方法,根据集合元素类型和嵌套状态判断输出格式:
import yaml from yaml.representer import SafeRepresenter class CustomDumper(yaml.Dumper): def represent_list(self, data): # 判断是否为嵌套列表(父节点非根节点) is_nested = self.indent > self.default_flow_style_indent # 判断列表是否仅包含数字类型元素 all_numbers = all(isinstance(item, (int, float)) for item in data) if is_nested or all_numbers: # 嵌套列表或纯数字列表,用单行紧凑格式 return SafeRepresenter.represent_list(self, data) else: # 含字符串的顶层列表,用块格式逐行输出 return self.represent_sequence('tag:yaml.org,2002:seq', data, flow_style=False) def represent_dict(self, data): # 判断是否为嵌套字典 is_nested = self.indent > self.default_flow_style_indent # 判断字典值是否仅包含数字类型 all_numbers = all(isinstance(val, (int, float)) for val in data.values()) if is_nested or all_numbers: # 嵌套字典或纯数字值字典,用单行紧凑格式 return SafeRepresenter.represent_dict(self, data) else: # 含字符串值的顶层字典,用块格式逐行输出 return self.represent_mapping('tag:yaml.org,2002:map', data, flow_style=False) # 注册自定义的列表和字典表示逻辑 CustomDumper.add_representer(list, CustomDumper.represent_list) CustomDumper.add_representer(dict, CustomDumper.represent_dict) # 测试数据 test_data = { "Strings": [ "A very very long string", "A very very long string2", "A very very long string3", "A very very long string4", "A very very long string5", "A very very long string8" ], "Numbers": [1,2,3,4,5,6,7,8,9], "StringsDict": [ {"First": "A very very long string"}, {"Second": "A very very long string8"} ], "NumbersDict": {"First": 12, "Second": 156}, # 验证嵌套集合格式 "NestedExample": { "InnerNumList": [10, 20, 30], "InnerNumDict": {"X": 100, "Y": 200} } } # 导出符合要求的YAML print(yaml.dump(test_data, Dumper=CustomDumper, default_flow_style=None, sort_keys=False))
代码说明
- 嵌套状态判断:通过当前缩进值与默认流格式缩进值的对比,识别嵌套集合,强制用单行格式输出。
- 元素类型校验:检查集合内元素(字典校验值)是否全为数字,纯数字集合采用单行紧凑格式。
- 格式切换逻辑:非嵌套且包含字符串的集合,使用块格式让每个元素单独占一行;其他情况使用流格式输出。
- 附加配置:
sort_keys=False保证输出键顺序与原字典一致,default_flow_style=None让自定义逻辑主导格式选择。
内容的提问来源于stack exchange,提问作者Stein
相关产品推荐
相关产品推荐

