ruamel.yaml加载转储丢失重复值元素,如何配置保留?
解决思路
问题根源
核心问题不是dump阶段的配置缺失,而是加载阶段的数据丢失:
- YAML语法中
{1,1,1}表示集合(set),而Python原生set自动去重,当ruamel.yaml用typ='safe'加载时,会将这类集合解析为Python的set,重复元素在加载完成后就已被剔除,后续dump自然无法输出重复项。 allow_duplicate_keys配置仅针对YAML映射(键值对)中的重复键,对集合类型的重复元素无效。
解决方案
要保留重复元素,需修改数据结构或加载逻辑,以下是两种可行方案:
方案1:将集合转换为列表
既然集合无法保留重复项,可先将输入字符串中的集合语法{x,x,x}替换为列表语法[x,x,x],加载后得到Python的list即可保留重复元素:
# 修改输入处理部分 dit="{p_d: {p: a0, nb: 0, be: {ar: {1, 1, 1, 1}}, bb: {tt: {dt: {10, 10}, vl: {0}, rl: {0}, sf: {10, 20}, ef: {10, 20}}}}}" # 把集合的{}替换为列表的[] yaml_str = re.sub(r'\{(\d+(?:,\s*\d+)*)\}', r'[\1]', dit) # 后续加载和dump逻辑不变 yaml = ruamel.yaml.YAML() yaml.default_flow_style = False # ... 其余代码不变
dump后的输出会以列表形式保留重复元素,若需要接近原集合的格式,可额外配置列表的输出样式。
方案2:自定义集合加载器
如果必须保留类似集合的输出格式,可自定义ruamel.yaml的构造器和代表器,将YAML集合解析为允许重复的自定义容器:
from ruamel.yaml import YAML, Constructor, Representer # 自定义允许重复的集合类 class DuplicateSet(list): pass # 自定义构造器:将YAML集合解析为DuplicateSet def construct_duplicate_set(loader, node): return DuplicateSet(loader.construct_sequence(node)) # 自定义代表器:将DuplicateSet输出为类似集合的格式 def represent_duplicate_set(dumper, data): return dumper.represent_sequence('tag:yaml.org,2002:set', data, flow_style=True) # 注册构造器和代表器 yaml = YAML() yaml.constructor.add_constructor('tag:yaml.org,2002:set', construct_duplicate_set) yaml.representer.add_representer(DuplicateSet, represent_duplicate_set) yaml.default_flow_style = False # 后续加载和dump逻辑不变
这种方式可以在输出时保留类似集合的{}格式,同时保留重复元素。
内容的提问来源于stack exchange,提问作者Vimo
相关产品推荐
相关产品推荐

