pyjq报错Cannot iterate over string,如何过滤boto3 IAM角色?
问题原因
报错「Cannot iterate over string」是因为你将page['Roles']序列化为JSON字符串后传给了pyjq.all(),但pyjq接受的是Python原生数据结构(列表/字典),而非序列化后的字符串。当pyjq尝试遍历字符串时,自然会抛出无法迭代字符串的错误。
解决步骤
1. 移除JSON序列化步骤
直接将page['Roles']这个Python列表传给pyjq,不需要用json.dumps()转换。
2. 处理Statement字段的两种格式
IAM角色的AssumeRolePolicyDocument中,Statement字段可能是单个字典或字典列表,需要统一处理成可迭代的列表,避免遍历出错。可以用[.] | flatten[]将单个对象转为列表后展开。
3. 筛选符合条件的角色
根据你的需求(筛选Principal为AWS的角色,排除Principal为service的角色),构造jq查询过滤掉包含service类型Principal的角色,再提取剩余角色中的AWS类型Principal。
修正后的代码
import pyjq import boto3 client = boto3.client("iam") paginator = client.get_paginator('list_roles') response_iterator = paginator.paginate() for page in response_iterator: # 直接使用Python原生列表,无需JSON序列化 roles = page['Roles'] # jq查询:过滤无service principal的角色,提取AWS principal filtered_principals = pyjq.all(""" .[] # 筛选所有Statement中都没有service类型Principal的角色 | select( .AssumeRolePolicyDocument.Statement | [.] | flatten[] | all(.Principal.service | not) ) # 处理Statement的单/列表格式,提取AWS principal | .AssumeRolePolicyDocument.Statement | [.] | flatten[] | .Principal.AWS """, roles) print(filtered_principals)
可选调整
如果你只是想提取所有包含AWS类型Principal的角色(即使该角色同时包含service类型Principal),可以修改jq查询为:
filtered_principals = pyjq.all(""" .[] | .AssumeRolePolicyDocument.Statement | [.] | flatten[] | select(.Principal.AWS) | .Principal.AWS """, roles)
内容的提问来源于stack exchange,提问作者prashanth pallu
相关产品推荐
相关产品推荐

