Ansible模块出现TypeError: 'itertools.imap'无__getitem__属性的原因及解决
问题原因及解决方案
为什么会出现这个错误?
你遇到的问题核心是Python中map()函数的返回值类型在不同环境下不一致:
- 在你本地Python控制台中,默认的
map()返回的是一个列表(list对象),所以你可以直接用下标[0]访问第一个元素。 - 但在Ansible模块的运行环境中,大概率是导入了
from future_builtins import map(Ansible为了向Python3兼容,可能默认启用了这类兼容设置),此时map()返回的是itertools.imap对象——这是一个迭代器,迭代器不支持通过下标__getitem__来访问元素,所以你调用plgns[0]时就会抛出TypeError。
你的Vagrant节点用的是Python 2.7.5,这个版本本身支持future_builtins模块,当Ansible模块加载时引入了这个模块的map,就触发了这个问题。
正确的写法有这几种:
1. 显式将迭代器转为列表(你的临时方案其实就是这个,这是很稳妥的写法)
直接把map的结果转成列表,这样不管map返回什么,都能通过下标访问:
plgns = list(map(os.path.basename, glob.glob(glb))) plgn_installed = plgns[0]
2. 用next()获取迭代器的第一个元素
如果确定结果至少有一个元素,可以直接用next()来取第一个值,避免转换整个列表(适合数据量较大的场景):
plgns = map(os.path.basename, glob.glob(glb)) plgn_installed = next(plgns) # 如果担心没有元素的话,可以加默认值:next(plgns, None)
3. 用列表推导式替代map
列表推导式在Python2和Python3中行为一致,都是返回列表,也能避免环境差异的问题:
plgns = [os.path.basename(p) for p in glob.glob(glb)] plgn_installed = plgns[0]
额外提醒
如果你的插件目录可能为空,建议加个判断,避免IndexError或者StopIteration错误:
jar_files = glob.glob(glb) if not jar_files: # 处理没有插件的情况,比如返回错误或者跳过 return has_changed, {"msg": "No plugin jars found"} plgn_installed = os.path.basename(jar_files[0])
内容的提问来源于stack exchange,提问作者onknows
相关产品推荐
相关产品推荐

