PyYAML dumps字典出现多余标签及信息问题求助
解决yaml.dump输出冗余标签和信息的问题
问题描述
我不理解为何yaml.dump会在结果中添加标签和冗余信息:
源文件file.yml内容:
ssh_keys: user1: - key: key1 state: state1
想要添加的键:
key_to_add = { 'key': key2, 'state': state2 }
使用的代码:
import yaml with open('file.yml', 'r') as file: data = yaml.load(file) print(key_to_add) data['ssh_keys']['user1'].append(key_to_add) print(data) print(type(data)) print(yaml.dump(data))
得到的意外输出:
{'key': 'key2', 'state': 'state2'} {'ssh_keys': {'user1': [{'key': 'key1', 'state': 'state1'}, {'key': 'key2', 'state': 'state2'}]}} <class 'dict'> ssh_keys: user1: - key: 'key1' state: 'state1' - key: !!python/object/new:ansible.parsing.yaml.objects.AnsibleUnicode args: - key2 state: _column_number: 26 _data_source: /home/........... _line_number: 34 state: !!python/object/new:ansible.parsing.yaml.objects.AnsibleUnicode args: - state2 state: _column_number: 24 _data_source: /home/........... _line_number: 35
期望的输出:
ssh_keys: user1: - key: 'key1' state: 'state1' - key: 'key2' state: 'state2'
原因分析
出现这个问题的核心原因是:
- 使用
yaml.load加载文件时,Ansible的YAML解析器会把字符串转换成ansible.parsing.yaml.objects.AnsibleUnicode类型对象,而非Python原生str类型。 yaml.dump处理这类自定义对象时,无法直接序列化为普通字符串,只能输出完整的对象结构标签和冗余元数据。- 要添加的
key2和state2变量大概率也是AnsibleUnicode类型,进一步加剧了dump时的异常输出。
解决方案
方案1:安全加载并转换为原生字符串
替换yaml.load为yaml.safe_load避免加载自定义类型,同时递归转换所有AnsibleUnicode对象为原生str:
import yaml from ansible.parsing.yaml.objects import AnsibleUnicode def convert_to_native_str(obj): # 递归转换所有自定义字符串对象为原生str if isinstance(obj, AnsibleUnicode): return str(obj) elif isinstance(obj, dict): return {convert_to_native_str(k): convert_to_native_str(v) for k, v in obj.items()} elif isinstance(obj, list): return [convert_to_native_str(item) for item in obj] return obj with open('file.yml', 'r') as file: data = yaml.safe_load(file) # 转换已加载数据中的自定义类型 data = convert_to_native_str(data) # 确保新增键值为原生字符串 key_to_add = { 'key': str(key2), 'state': str(state2) } data['ssh_keys']['user1'].append(key_to_add) # 输出干净的YAML结构 print(yaml.dump(data, default_style=None))
方案2:为AnsibleUnicode添加自定义序列化器
告诉PyYAML如何将AnsibleUnicode对象序列化为普通字符串:
import yaml from ansible.parsing.yaml.objects import AnsibleUnicode # 定义自定义序列化规则 def represent_ansible_unicode(dumper, data): return dumper.represent_str(str(data)) # 注册序列化器 yaml.add_representer(AnsibleUnicode, represent_ansible_unicode) with open('file.yml', 'r') as file: data = yaml.load(file) key_to_add = { 'key': key2, 'state': state2 } data['ssh_keys']['user1'].append(key_to_add) # 输出正常格式的YAML print(yaml.dump(data))
验证结果
使用任一方案后,yaml.dump都会输出期望的干净YAML结构:
ssh_keys: user1: - key: 'key1' state: 'state1' - key: 'key2' state: 'state2'
内容的提问来源于stack exchange,提问作者timothepoznanski
相关产品推荐
相关产品推荐

