Python调用Microsoft Graph API插Oracle表报KeyError: 'value'如何解决
问题原因分析
- 核心问题是你没有对接口请求的返回结果做合法性校验,直接强制读取
value字段,当接口返回异常时就会触发KeyError:- 当调用群组所有者接口触发权限不足、调用频率超限、GroupID非法等问题时,接口会返回错误结构,不会携带
value字段 - 哪怕请求返回200状态码,也建议先判断字段存在性再读取,避免边界情况报错
- 当调用群组所有者接口触发权限不足、调用频率超限、GroupID非法等问题时,接口会返回错误结构,不会携带
- 额外隐藏风险:就算
value字段存在,所有者属性如果为空(比如部分用户没有填写职务、手机号),直接读取owner['jobTitle']这类字段也会触发KeyError,同时你原代码里的表名拼写<tabel>存在笔误,应该是<table>。
修复方案
你可以按照下面的逻辑修改代码:
import requests import datetime url = "https://graph.microsoft.com/v1.0/groups/" Group_owner_url = "https://graph.microsoft.com/v1.0/groups/{}/owners/" rows =[] sysdate = datetime.datetime.now() # 群组列表请求增加状态码和字段校验 response = requests.request("GET", url, headers=headers, data=payload) if response.status_code == 200: data = response.json() if 'value' in data: for group in data['value']: if 'id' in group: rows.append(group['id']) else: print(f"群组列表请求失败,状态码:{response.status_code},返回内容:{response.text}") for GroupID in rows: url_owner = Group_owner_url.format(GroupID) response_owner = requests.request("GET", url_owner, headers=headers, data=payload) # 先校验请求状态码 if response_owner.status_code != 200: print(f"群组{GroupID}所有者查询失败,状态码:{response_owner.status_code},返回内容:{response_owner.text}") continue owner_data = response_owner.json() # 先判断value字段存在再遍历 if 'value' not in owner_data: print(f"群组{GroupID}返回结果无value字段,返回内容:{owner_data}") continue for owner in owner_data['value']: # 用get方法读取字段,不存在默认返回空字符串,避免KeyError cursor.execute( "insert into <table> (GROUP_ID, OWNER_NAME, OWNER_GIVENNAME, OWNER_SURNAME, JOB_TITLE, USER_PRINCIPAL_NAME, EMAIL, MOBILE_PHONE, OFFICE_LOCATION, DB_CREATE_TIME)values (:1, :2, :3, :4, :5, :6, :7, :8, :9, :10)", ( GroupID, owner.get('displayName', ''), owner.get('givenName', ''), owner.get('surname', ''), owner.get('jobTitle', ''), owner.get('userPrincipalName', ''), owner.get('mail', ''), owner.get('mobilePhone', ''), owner.get('officeLocation', ''), sysdate ) ) cursor.close() connect.commit() connect.close()
排查建议
你可以先运行加了打印的代码,看触发KeyError的时候接口返回的具体内容,大概率是以下两种情况:
- 权限问题:检查应用注册的权限有没有开通
Group.Read.All这类群组读取权限,并且已经管理员同意 - 调用限流:短时间请求量太大触发接口限流,这种情况可以加指数退避的重试逻辑
内容的提问来源于stack exchange,提问作者Sajjad
相关产品推荐
相关产品推荐

