You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 13:22:51