ruamel.yaml与yamllint序列缩进冲突问题求解
解决ruamel.yaml与yamllint的缩进兼容问题
问题重现
原始YAML内容:
root: - foo: - bar: 1 - baz: 2
用配置offset=2、sequence=4的ruamel.yaml读写后,输出变为:
root: - foo: - bar: 1 - baz: 2
该格式不符合预期,且yamllint报错:
error wrong indentation: expected 4 but found 6 (indentation)
原因解析
- ruamel.yaml的缩进计数逻辑和常规解析器(如PyYAML)存在差异:
sequence=4指定序列元素相对于父节点的缩进为4个空格,offset=2指定键值对的缩进为2个空格。嵌套序列时,ruamel会将两个缩进值叠加,导致子序列元素总缩进达到6个空格,触发yamllint的缩进规则报错。 - 额外说明:如果你的原始YAML意图是让
foo的值包含bar和baz的列表,那原始缩进其实不符合YAML规范——子序列元素必须比父键(foo)有更大的缩进,ruamel输出的格式才是合法结构;但如果需要保留原始格式,就得调整ruamel的配置。
解决方案
方案1:合规格式+yamllint兼容
如果目标是结构合法且通过yamllint检查,将ruamel.yaml的sequence缩进调整为和offset一致的2:
from ruamel.yaml import YAML yaml = YAML() # 让sequence缩进与offset匹配,避免嵌套时缩进叠加 yaml.indent(offset=2, sequence=2) # 读写示例 with open("input.yaml", "r") as f: data = yaml.load(f) with open("output.yaml", "w") as f: yaml.dump(data, f)
生成的输出会和原始格式一致:
root: - foo: - bar: 1 - baz: 2
同时修改yamllint的配置文件(.yamllint),将序列缩进设为2:
rules: indentation: sequences: 2
方案2:强制保留原始非规范缩进
如果必须保留原始的非规范缩进(即使存在结构解析风险),可以开启ruamel的格式保留配置:
from ruamel.yaml import YAML yaml = YAML() yaml.preserve_quotes = True # 缩进配置匹配原始格式 yaml.indent(offset=2, sequence=2) yaml.default_flow_style = False # 读写操作 with open("input.yaml", "r") as f: data = yaml.load(f) with open("output.yaml", "w") as f: yaml.dump(data, f)
⚠️ 注意:这种方式可能导致不同解析器解析出不同结构,因为原始缩进不符合YAML规范,谨慎使用。
内容的提问来源于stack exchange,提问作者Avl8
相关产品推荐
相关产品推荐

