使用discord.py开发时如何避免超出Discord API速率限制?
问题原因
discord.py 自带的 commands.cooldown 装饰器的冷却校验逻辑,是在命令解析、上下文初始化完成后才会触发,这一过程本身已经产生了基础API请求;另外默认的冷却触发后会自动发送错误提示消息,也会额外产生API调用,所以就算触发冷却也会被计入请求次数。
解决方案
方案1:上游事件层提前拦截(推荐)
在on_message事件(命令处理的最上游)提前做冷却校验,还未进入命令解析流程就拦截超限请求,完全不会产生额外API调用:
import time import discord from discord.ext import commands # 冷却配置:键为用户ID,值为对应命令的上次调用时间戳,可按命令拆分存储 user_cooldowns = {} # 全局单命令冷却时间,单位秒,可按需调整为不同命令不同值 DEFAULT_COOLDOWN = 5 bot = commands.Bot(command_prefix='!', intents=discord.Intents.all()) @bot.event async def on_message(message): # 直接忽略机器人自身消息 if message.author.bot: return # 仅校验带命令前缀的消息 if message.content.startswith(bot.command_prefix): user_id = message.author.id # 这里可以提取命令名,实现不同命令不同冷却逻辑 # command_name = message.content.split()[0][len(bot.command_prefix):] now = time.time() # 冷却校验 if user_id in user_cooldowns and now - user_cooldowns[user_id] < DEFAULT_COOLDOWN: # 直接返回,不触发后续任何命令处理逻辑,无API调用产生 return # 更新冷却时间 user_cooldowns[user_id] = now # 正常放行符合要求的命令 await bot.process_commands(message)
方案2:拦截冷却错误,禁用默认响应
如果不想改动原有commands.cooldown的写法,可以重写命令错误处理事件,拦截冷却错误且不发送任何响应,减少额外API调用:
@bot.event async def on_command_error(ctx, error): if isinstance(error, commands.CommandOnCooldown): # 直接跳过,不发送任何冷却提示消息,避免额外API请求 pass else: # 其他错误按原有逻辑处理 raise error
补充说明
如果你的机器人用户量较大,可以将冷却存储从内存字典替换为Redis等外部存储,避免内存占用过高,同时支持多实例部署时的冷却状态同步。
内容的提问来源于stack exchange,提问作者ethanp
相关产品推荐
相关产品推荐

