ruamel.yaml序列化丢失锚点且跳过同层级后续别名问题排查
关于ruamel.yaml处理YAML合并键(<<)顺序式别名的问题
问题场景
原始YAML配置内容:
--- sp-database: &sp-database DATABASE_NAME: blah DATABASE_PORT: 5432 DATABASE_SCHEMA: public DATABASE_USERNAME: foo DATABASE_DRIVER: bar DATABASE_TYPE: pg rabbit: &rabbit RABBIT_PORT: 5672 RABBIT_USERNAME: foo sp-env: &sp-env <<: *sp-database <<: *rabbit REDIS_PORT: 6379
使用以下Python代码读取并转储该YAML:
def blah(self): values_file = './src/values.yaml' with open(values_file, 'r') as stream: data = self.yaml.load(stream) values_file='./src/values1.yaml' with open(values_file, 'w') as file: self.yaml.indent(sequence=4, offset=2) self.yaml.dump(data, file)
操作中遇到问题:ruamel.yaml会丢失锚点信息,并且跳过同层级第一个<<:后的其他别名,最终转储的结果只保留了第二个别名的合并内容。将合并键改为数组形式后即可正常工作:
sp-env: &sp-env <<: [ *sp-database, *rabbit ] REDIS_PORT: 6379
原因解析
- YAML规范对重复键的定义:YAML核心规范中,同一个映射表(字典)内不允许存在重复键。多数解析器处理重复键时,只会保留最后一个出现的键值对。连续写两个
<<:属于重复键<<的写法,不符合规范推荐用法。 - ruamel.yaml的解析逻辑:ruamel.yaml解析重复的
<<键时,会直接用后一个值覆盖前一个,导致第一个别名*sp-database的合并逻辑被丢弃。同时锚点信息在解析过程中无法被正确保留——因为解析后的内存结构里没有多个合并项的记录,转储自然无法还原原始的顺序式别名写法。 - 数组形式的合法性:YAML规范明确支持合并键的值为别名数组,这种写法会让解析器依次合并数组中每个别名指向的映射表内容,属于标准合并用法。ruamel.yaml能正确识别这种结构,保留合并逻辑与锚点信息,因此转储后能正常工作。
内容的提问来源于stack exchange,提问作者Recur
相关产品推荐
相关产品推荐

