使用ruamel.yaml导出YAML时移除空字典值(Ansible清单场景)
解决ruamel.yaml导出Ansible清单时空字典显示为
{}的问题 问题场景
编写脚本从CMDB获取数据生成Ansible清单,使用ruamel.yaml导出YAML时,主机对应的空字典会被渲染为{},不符合预期格式,需要改为仅显示主机名加冒号的形式。
现有代码
groups = { "all": { "children": { "team_servers": { "hosts": dict() }, "tool_servers": { "hosts": dict() }, "ungrouped": { "hosts": ungrouped } } } } for p in partition: if "tools" in p.name: if host.name not in groups["all"]["children"]["tool_servers"]: groups["all"]["children"]["tool_servers"]["hosts"][host.name] = dict() def return_yaml(self): yml = yaml.YAML() yml.explicit_start = True data = json.loads(self.inventory, object_pairs_hook=yaml.comments.CommentedMap) yaml.scalarstring.walk_tree(data) yaml_inventory = yaml.dump(data, default_flow_style=True) print(yml.dump(data, sys.stdout))
当前输出
--- all: children: tool_servers: hosts: hostname1: {} hostname2: {} hostname3: {} hostname4: {}
期望输出
--- all: children: tool_servers: hosts: hostname1: hostname2: hostname3: hostname4:
解决方案
核心修改点
将主机对应的空字典赋值改为None,ruamel.yaml会将None序列化为空值(仅保留键与冒号),完全匹配Ansible清单的格式要求。
修改后的代码片段
- 调整主机赋值逻辑:
# 原代码 groups["all"]["children"]["tool_servers"]["hosts"][host.name] = dict() # 修改为 groups["all"]["children"]["tool_servers"]["hosts"][host.name] = None
- 可选优化:统一使用ruamel.yaml的实例进行序列化,避免混用原生yaml模块:
def return_yaml(self): yml = yaml.YAML() yml.explicit_start = True data = json.loads(self.inventory, object_pairs_hook=yaml.comments.CommentedMap) yaml.scalarstring.walk_tree(data) # 移除原生yaml.dump调用,统一用ruamel的yml实例 yml.dump(data, sys.stdout)
原理说明
ruamel.yaml对不同类型的空值处理逻辑不同:
- 空字典
dict()会被序列化为{} None会被序列化为无值的键值对(仅显示key:),这正是Ansible清单中无变量主机的标准写法。
内容的提问来源于stack exchange,提问作者mwas01
相关产品推荐
相关产品推荐

