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

Flask页面刷新时循环请求Discord API返回KeyError故障如何解决

故障原因
  • 核心触发原因是Discord Bot API触发了速率限制:你当前代码每个用户ID要发起2次完全重复的GET请求查询用户信息,请求量直接翻倍,短时间内频繁刷新/定时请求会很快触达Discord的接口调用频次限制,此时接口返回的是速率限制报错响应,结构体中不存在username、discriminator字段,直接硬取字段就会抛出KeyError。请求间隔越短,触发速率限制的速度越快,和你观测到的报错规律完全匹配。
  • 缺少请求异常校验逻辑:代码未对Discord接口的返回状态码、响应结构做任何校验,除了速率限制外,Token失效、用户ID无效、网络波动等场景都会导致返回结构不符合预期,直接取字段必然报错。
  • 可选排查点:Flask默认以多线程模式运行,模块级全局变量如果在多个请求中同时被修改,可能出现变量内容被篡改的情况,也可能间接导致取到异常的userid值进而请求失败。
修复方案

1. 优化接口请求逻辑,合并重复请求

同一个用户ID只发起一次请求,直接取全量需要的字段,同时添加本地缓存避免重复查询,从根源上降低请求频次:

import time
# 提前初始化缓存,可放在模块顶部,避免重复查询
user_cache = {}
CACHE_EXPIRE = 3600 # 缓存有效期1小时,可自行调整

# 原第一个循环优化后逻辑
for uid in useridlist[:5]: # 取前5个,和原range(0,5)逻辑一致
    user_tag = ""
    # 先查缓存,有有效数据直接用
    if str(uid) in user_cache and time.time() - user_cache[str(uid)]['update_time'] < CACHE_EXPIRE:
        user_tag = user_cache[str(uid)]['tag']
    else:
        # 每个用户只发一次请求
        resp = requests.get(
            f"https://discord.com/api/v9/users/{uid}",
            headers={"Authorization": "Bot BOTTOKEN"}
        )
        # 校验响应状态
        if resp.status_code != 200:
            # 遇到速率限制可先重试,或者直接兜底用uid展示
            if resp.status_code == 429:
                retry_after = resp.json().get('retry_after', 1)
                time.sleep(retry_after)
                # 重试一次,也可以跳过重试直接走兜底逻辑
                resp = requests.get(
                    f"https://discord.com/api/v9/users/{uid}",
                    headers={"Authorization": "Bot BOTTOKEN"}
                )
            # 请求还是失败就用uid兜底,避免报错
            user_tag = f"UID:{uid}"
        else:
            user_data = resp.json()
            # 用get方法取值,避免字段缺失抛出KeyError
            username = user_data.get('username', '未知用户')
            discriminator = user_data.get('discriminator', '0000')
            user_tag = f"{username}#{discriminator}"
            # 写入缓存
            user_cache[str(uid)] = {
                'tag': user_tag,
                'update_time': time.time()
            }
    userIDtoName.append(user_tag)

2. 优化后续循环逻辑,添加兜底校验

对coins字典的取值也添加容错逻辑,避免用户ID不存在时抛出KeyError:

# 取三个列表的最小长度作为循环边界,避免索引越界
loop_len = min(5, len(useridlist), len(userIDtoName))
for j in range(loop_len):
    user_coins = coins.get(str(useridlist[j]), 0)
    coinslist.append(user_coins)

loop_len = min(5, len(userIDtoName), len(coinslist))
for l in range(loop_len):
    leaderboardlist.append(f"{userIDtoName[l]} => {coinslist[l]}")

3. 可选优化(规避全局变量线程安全问题)

如果存在多请求并发场景,建议不要使用模块级全局变量存储本次请求的临时数据,改为在请求函数内部初始化userIDtoName、coinslist、leaderboardlist变量,避免多线程互相篡改数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 13:06:03