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

使用ruamel.yaml生成Ansible inventory文件报错排查

问题根因

两个低级问题叠加导致的报错,和YAML语法、Python代码逻辑本身无关:

  • 你代码中指定的输出文件名是db.yaml,但Ansible命令里加载的inventory是greenhouses.yml,如果没有手动重命名,Ansible实际加载的要么是旧文件、要么是其他文件,和你代码生成的内容无关。
  • ruamel.yaml默认直接写入Path对象时,在Windows环境下会使用系统默认编码(通常为GBK)写入文件,同时可能附带UTF-8 BOM头;另外你写的defaultdict转换方法只处理了外层字典,嵌套的内层defaultdict在部分ruamel.yaml版本下会被加上Python专属类型标记,Ansible解析时不会报格式错误,但读取主机连接配置时会拿到None值,最终触发expected str, bytes or os.PathLike object, not NoneType报错。

这也是为什么你手动粘贴同样内容保存就能正常运行——手动保存的文件默认是无BOM的UTF-8编码,也没有隐式类型标记。

修复代码

不要直接把Path对象传给dump方法,手动指定编码打开文件,同时递归把所有嵌套defaultdict转成普通Python字典,对齐Ansible的YAML缩进规范:

from collections import defaultdict
from pathlib import Path
import ruamel.yaml

# 这里文件名要和Ansible -i参数指定的文件名一致,不要写错
outfile = Path('greenhouses.yml')

db = defaultdict(lambda: defaultdict(list))
db['greenhouse1']['fruits'].append('apples')  
db['greenhouse1']['fruits'].append('oranges')
db['greenhouse1']['colors'] = ["red", "orange"]
db['greenhouse2']['fruits'].append('banana')

# 递归转换所有嵌套defaultdict为普通dict
def to_plain_dict(data):
    if isinstance(data, defaultdict):
        data = dict(data)
    if isinstance(data, dict):
        return {k: to_plain_dict(v) for k, v in data.items()}
    if isinstance(data, list):
        return [to_plain_dict(item) for item in data]
    return data

yaml = ruamel.yaml.YAML()
# 对齐Ansible默认YAML缩进风格,避免旧版本兼容性问题
yaml.indent(mapping=2, sequence=4, offset=2)

# 手动指定无BOM的UTF-8编码,使用Unix风格换行写入
with open(outfile, 'w', encoding='utf-8', newline='\n') as f:
    yaml.dump(to_plain_dict(db), f)
验证步骤
  • 生成文件后执行ansible-inventory -i greenhouses.yml --list,确认输出的结构中greenhouse1、greenhouse2主机和对应的fruits、colors变量都被正确识别,没有异常键名。
  • 再执行ansible all -m win_ping -i greenhouses.yml测试连通性,不会再出现NoneType报错。

补充:最开始排查时被报错里的None误导,以为是inventory结构缺字段,实际上是文件编码和隐式类型标记导致Ansible读出来的配置是空值,和inventory结构、Playbook、角色逻辑都没有关系。

内容的提问来源于stack exchange,提问作者Nicholas Tripp

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 04:09:29