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

为什么我的Discord机器人on_ready函数无限循环且无法写入PostgreSQL数据

原因分析

on_ready无限循环的根因

  • DiscordComponents(bot)初始化放在on_ready内部,该组件初始化会修改bot实例的内部状态、触发网关重连,而on_ready本身会在bot每次重连成功后自动调用,形成循环触发逻辑
  • 空except语句捕获了所有异常,包括协程中断、数据库连接断开等错误,没有错误抛出,bot不会崩溃退出,会持续重复执行on_ready
  • 全局共享的数据库连接/游标在大量循环插入时容易出现阻塞、断开,触发bot内部重连逻辑,进一步加剧循环问题

数据库无法写入的根因

  • 表结构定义错误:id字段设置为BIGSERIAL类型,这是PostgreSQL的自增主键类型,不需要主动传入值。你主动插入Discord用户ID作为主键值,会触发主键冲突,同时自增序列不会同步更新,后续插入全部失败。
  • SQL构造错误:直接用字符串拼接构造SQL语句,当member对象转字符串后包含单引号时,会触发SQL语法错误,所有错误都被空except吞掉,插入直接跳过。
  • 网关权限缺失:discord.py v1.5及以上版本需要在开发者后台开启成员网关意图,同时代码中显式声明intents.members = True,否则guild.members只能获取到bot自身,没有其他成员数据可以插入。
修复方案
  1. 调整组件初始化位置
    把DiscordComponents(bot)移到on_ready外部,放在bot实例化之后的全局位置,避免重复初始化触发重连。

  2. 增加on_ready执行标记
    避免事件被重复触发:

is_ready = False

@bot.event
async def on_ready():
    global is_ready
    if is_ready:
        return
    is_ready = True
    # 原有逻辑
  1. 修正表结构和SQL操作
  • 把主键字段类型改为BIGINT,适配Discord用户ID:
CREATE TABLE IF NOT EXISTS users (
    name VARCHAR(255), 
    id BIGINT PRIMARY KEY, 
    xp INT
);
  • 使用参数化查询代替字符串拼接,避免语法错误和注入风险,同时明确捕获主键重复异常:
from psycopg2 import IntegrityError

# 插入逻辑替换为
try:
    cursor.execute(
        "INSERT INTO users (name, id, xp) VALUES (%s, %s, %s)",
        (str(member), member.id, 0)
    )
except IntegrityError:
    # 用户已存在,直接跳过
    continue
  1. 开启成员意图
    实例化bot时显式声明成员意图:
import discord
from discord.ext import commands

intents = discord.Intents.default()
intents.members = True
bot = commands.Bot(command_prefix="你的前缀", intents=intents)

同时需要到Discord开发者后台的Bot设置页,开启Server Members Intent开关。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 09:36:04