Discord.py机器人无报错循环结束后触发on_ready疑似重启问题求助
问题根因
- 核心原因是事件循环被同步调用阻塞:代码中使用的
time.sleep(180)是同步阻塞方法,会直接卡死discord.py的整个异步事件循环,导致网关心跳包无法正常发送给Discord服务器。超过心跳阈值后Discord会主动断开机器人连接,客户端自动重连后就会再次触发on_ready事件,就是你观测到的重复打印启动消息的原因。接入的guild数量越多,事件循环需要处理的任务量越大,阻塞导致的心跳超时概率就越高,和你观测到的故障频率变化完全匹配。 on_ready本身设计上就支持多次触发,所有重连场景都会调用该事件,你将定时任务启动逻辑放在on_ready中,还叠加了时间判断的阻塞循环,属于不符合discord.py开发规范的写法。- 无错误日志是因为心跳超时属于网关层面的静默断开,默认配置下未开启网关事件日志时不会打印相关报错信息。
修复方案
- 替换所有同步阻塞调用:将
time.sleep(180)改为异步休眠await asyncio.sleep(180),调用异步方法需要添加await关键字,同时不要在on_ready事件中编写长周期等待逻辑。 - 定时任务改用
discord.ext.tasks官方模块实现15分钟间隔的调度,不要自行编写时间判断逻辑。定时任务不要在on_ready中启动,改为在客户端初始化完成后、启动连接前启动,或者添加全局状态变量判断任务是否已经启动,避免重复启动。 - 循环任务中的所有API请求必须使用异步HTTP库(如aiohttp),不要使用requests这类同步请求库,避免再次阻塞事件循环,同时配置请求限流逻辑,避免触发Discord API速率限制。
- 开启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
相关产品推荐
相关产品推荐

