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

Discord.py机器人无报错循环结束后触发on_ready疑似重启问题求助

问题根因

  • 核心原因是事件循环被同步调用阻塞:代码中使用的time.sleep(180)是同步阻塞方法,会直接卡死discord.py的整个异步事件循环,导致网关心跳包无法正常发送给Discord服务器。超过心跳阈值后Discord会主动断开机器人连接,客户端自动重连后就会再次触发on_ready事件,就是你观测到的重复打印启动消息的原因。接入的guild数量越多,事件循环需要处理的任务量越大,阻塞导致的心跳超时概率就越高,和你观测到的故障频率变化完全匹配。
  • on_ready本身设计上就支持多次触发,所有重连场景都会调用该事件,你将定时任务启动逻辑放在on_ready中,还叠加了时间判断的阻塞循环,属于不符合discord.py开发规范的写法。
  • 无错误日志是因为心跳超时属于网关层面的静默断开,默认配置下未开启网关事件日志时不会打印相关报错信息。

修复方案

  1. 替换所有同步阻塞调用:将time.sleep(180)改为异步休眠await asyncio.sleep(180),调用异步方法需要添加await关键字,同时不要在on_ready事件中编写长周期等待逻辑。
  2. 定时任务改用discord.ext.tasks官方模块实现15分钟间隔的调度,不要自行编写时间判断逻辑。定时任务不要在on_ready中启动,改为在客户端初始化完成后、启动连接前启动,或者添加全局状态变量判断任务是否已经启动,避免重复启动。
  3. 循环任务中的所有API请求必须使用异步HTTP库(如aiohttp),不要使用requests这类同步请求库,避免再次阻塞事件循环,同时配置请求限流逻辑,避免触发Discord API速率限制。
  4. 开启discord.py日志输出:在代码开头添加日志配置,将日志等级设为INFO即可查看网关连接、断开的相关日志,确认故障场景是否为网关重连导致。

参考修正代码

import asyncio
import datetime as dt
from discord.ext import tasks

# 定时任务全局定义
@tasks.loop(minutes=15)
async def transactions():
    # 原有循环任务逻辑写在这里
    pass

@client.event
async def on_ready():
    print("Bot is ready.")
    if not transactions.is_running():
        # 自动对齐到15分钟刻度,替代原有的硬编码时间判断
        now = dt.now()
        wait_seconds = (15 - now.minute % 15) * 60 - now.second
        await asyncio.sleep(wait_seconds)
        transactions.start()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 22:39:02