使用ruamel.yaml加载YAML为字典并重新保存时如何保留值中的双引号
如何保留YAML字符串的双引号(ruamel.yaml)
你遇到的引号丢失问题,核心原因是你用json.dumps()和json.loads()把ruamel.yaml加载的特殊有序字典转成了普通Python字典——这一步会彻底丢掉ruamel.yaml为了保留格式(比如引号)而存储的元数据。ruamel.yaml的preserve_quotes=True配置只对它自己的CommentedMap/CommentedSeq类型生效,普通字典根本没有保存引号状态的能力。
解决方案:直接操作ruamel.yaml原生对象
去掉转普通字典的步骤,直接使用ruamel.yaml加载后的特殊对象修改数据,这样就能保留原始的引号格式。修改后的完整代码如下:
from fnmatch import fnmatch import os import ruamel.yaml # 初始化ruamel.yaml,开启引号保留配置 yaml = ruamel.yaml.YAML(typ='safe', pure=True) yaml.preserve_quotes = True yaml.explicit_start = True yaml.default_flow_style = False yaml.indent(mapping=2, sequence=4, offset=2) def _list_files(): ''' 递归列出目录下所有yaml文件 ''' pattern = "*.yaml" in_folder="./" all_files = [] for path, subdirs, files in os.walk(in_folder): for name in files: if fnmatch(name, pattern): f = os.path.join(path, name) all_files.append(f) return all_files def load_files(): ''' 递归加载yaml文件,以文件名作为键存储数据 ''' dict_tree = {} for sfile in _list_files(): with open(sfile, 'r') as stream: data_loaded = yaml.load(stream) dict_tree[sfile] = data_loaded return dict_tree # 加载YAML文件,直接使用ruamel.yaml的原生格式对象 load_yaml_files = load_files() # 直接修改数据,无需转成普通字典 load_yaml_files['./y.yaml']["lev1"]["lev2"][0]["new_item"] = "test" new_dict = load_yaml_files["./y.yaml"] # 保存修改后的YAML文件 dst_file = "dest.yaml" with open(dst_file, 'w') as yaml_file: yaml.dump(new_dict, yaml_file)
关键改动说明
- 移除
to_dict函数:这个函数是问题的根源,JSON序列化会把ruamel.yaml的特殊类型转成普通字典,彻底丢失引号、缩进等格式元数据。 - 直接操作原生对象:ruamel.yaml加载返回的
CommentedMap和CommentedSeq会完整保留原始YAML的格式信息,preserve_quotes=True配置才能正常生效。
修改后生成的dest.yaml会完美保留你期望的双引号:
lev1:
lev2:
- name: schema
new_item: test
templates:
- name: temp1
deploy_onpr: "yes"
deploy_cl: "no"
额外提示
如果确实需要临时转成普通字典处理,处理完后再转回ruamel.yaml的特殊类型会非常繁琐,不如从一开始就直接使用ruamel.yaml的原生对象操作,既能保证格式保留,又能正常修改数据。
内容的提问来源于stack exchange,提问作者ovntatar
相关产品推荐
相关产品推荐

