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

Python调用GitHub GraphQL API格式化查询触发KeyError问题求助

Fixing KeyError When Formatting GitHub GraphQL Audit Log Query in Python

我看你遇到的问题是Python脚本里的str.format()抛出了KeyError,这是因为你的GraphQL查询字符串里充满了花括号{},而Python的format()方法会把所有未转义的{}都当成占位符来处理——但你只准备了两个要替换的值(组织名和after参数),其他的花括号属于GraphQL语法,却被误判成需要填充的占位符,所以才会出现KeyError: '\n organization(login'这种错误。

解决方案:转义GraphQL中的花括号

要解决这个问题,你需要把GraphQL查询里所有不需要替换的花括号都转义成双花括号{{}},这样Python的format()方法就会把它们当成普通的单花括号输出,而只处理你指定的两个占位符。

修正后的查询字符串应该是这样的:

# 转义所有GraphQL语法的花括号,只保留需要替换的两个{}
Query = """ query {{ organization(login: '{}') {{ auditLog(first: 100, {}) {{ edges {{ node {{ ... on RepositoryAuditEntryData {{ repository {{ name }} }} ... on OrganizationAuditEntryData {{ organizationResourcePath organizationName organizationUrl }} ... on TeamAuditEntryData {{ teamName }} ... on TopicAuditEntryData {{ topicName }} ... on OauthApplicationAuditEntryData {{ oauthApplicationName }} ... on EnterpriseAuditEntryData {{ enterpriseResourcePath enterpriseUrl enterpriseSlug }} ... on AuditEntry {{ actorResourcePath action actorIp actorLogin operationType createdAt actorLocation {{ countryCode country regionCode region city }} #User 'Action' was performed on userLogin userResourcePath userUrl }} }} cursor }} pageInfo {{ endCursor hasNextPage hasPreviousPage }} }} }} }} """

另外,我注意到你原来的第二个占位符加了单引号'{}',其实可以去掉——因为当after变量是空字符串时,这部分会变成空,不会破坏GraphQL语法;当有值时,你已经在after = 'after: "%s"' % ...里加了正确的格式,替换后会变成auditLog(first: 100, after: "XYZ"),和你在Insomnia/Postman里的正确查询结构一致。

额外优化建议

  1. 检查请求状态码:除了检查返回的JSON里的errors,最好先判断result.status_code == 200,避免因为网络问题或权限错误导致的非JSON响应。
  2. 打印调试查询:在发送请求前可以先打印格式化后的查询字符串,确认语法是否正确:
    formatted_query = Query.format(org, after)
    print(formatted_query)
    result = requests.post('https://api.github.com/graphql', json={'query': formatted_query}, headers=headers)
    
  3. 确保headers正确:你的headers变量需要包含GitHub的认证token,比如:
    headers = {"Authorization": "Bearer YOUR_GITHUB_PERSONAL_ACCESS_TOKEN"}
    
    注意token需要有read:audit_log权限才能拉取审计日志。

修正后的完整脚本片段

import requests
import json
import time

headers = {"Authorization": "Bearer YOUR_GITHUB_TOKEN"}

# 转义后的GraphQL查询模板
Query = """ query {{ organization(login: '{}') {{ auditLog(first: 100, {}) {{ edges {{ node {{ ... on RepositoryAuditEntryData {{ repository {{ name }} }} ... on OrganizationAuditEntryData {{ organizationResourcePath organizationName organizationUrl }} ... on TeamAuditEntryData {{ teamName }} ... on TopicAuditEntryData {{ topicName }} ... on OauthApplicationAuditEntryData {{ oauthApplicationName }} ... on EnterpriseAuditEntryData {{ enterpriseResourcePath enterpriseUrl enterpriseSlug }} ... on AuditEntry {{ actorResourcePath action actorIp actorLogin operationType createdAt actorLocation {{ countryCode country regionCode region city }} userResourcePath userUrl }} }} cursor }} pageInfo {{ endCursor hasNextPage hasPreviousPage }} }} }} }} """

org_list = ["CoreDevOpsTools", "JIRA-Cloud"]
res = []

for org in org_list:
    after = ''
    while True:
        formatted_query = Query.format(org, after)
        # 可选:打印调试查询
        # print(formatted_query)
        result = requests.post('https://api.github.com/graphql', json={'query': formatted_query}, headers=headers)
        
        # 检查请求是否成功
        if result.status_code != 200:
            print(f"Request failed with status code: {result.status_code}")
            break
            
        json_data = json.loads(result.text)
        if 'errors' in json_data:
            print(json_data['errors'])
            break
            
        res_list = json_data['data']['organization']['auditLog']
        for items in res_list['edges']:
            res.append(items)
            
        if not res_list['pageInfo']['hasNextPage']:
            break
            
        after = 'after: "%s"' % res_list['edges'][-1]['cursor']
        time.sleep(1)

# 处理结果
print(f"Total audit log entries fetched: {len(res)}")

这样修改后,你的脚本应该就能正常运行,不会再抛出KeyError了。

内容的提问来源于stack exchange,提问作者Kishan Kumar Gupta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 11:02:48