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

如何在调用discord.py的bot.close()后不重启整个py文件重启机器人

调用bot.close()后无法复用原有实例启动的核心原因是该方法会销毁实例内部的aiohttp会话、WebSocket连接、运行时状态标记,原有实例的内部标记已经被置为已关闭,无法直接再次调用start()。

可用解决方案

推荐优先用方案1,兼容性最好,不会随着discord.py版本迭代失效

方案1:每次启动新建Bot实例(最稳妥)

不需要修改discord.py内部私有属性,不会因为版本更新失效,实现逻辑如下:

  • 不要全局复用同一个Bot实例,每次点击启动按钮时,重新初始化一个新的Bot对象,把你之前注册的命令、事件监听器、Cog加载逻辑全部重新执行一遍即可
  • 原有代码中把全局的bot变量改为当前界面类的实例属性,关闭后直接丢弃旧实例,启动时新建即可

修改后的参考代码:

# 单独抽离Bot实例创建逻辑,所有命令、事件、Cog注册都放在这个函数里
def create_bot_instance():
    from discord.ext import commands
    # 替换为你自己的Bot初始化参数,比如command_prefix、intents等
    bot = commands.Bot(command_prefix="!", intents=你的Intents配置)
    # 此处复制你之前所有的@bot.command、@bot.event、bot.load_extension等注册逻辑
    return bot

# 修改你的按钮点击事件
@asyncSlot()
async def on_btnStartBot_clicked(self):
    self.pushButton_startBot.setEnabled(False)
    if self.isBotRunning == False:
        self.statusbar.showMessage("Starting Bot...")
        # 每次启动新建全新的Bot实例
        self.bot = create_bot_instance()
        try:
            if isinstance(cfg["bot"]["token"], str) and cfg["bot"]["token"] != "":
                await self.bot.start(cfg["bot"]["token"])
            elif isinstance(cfg["bot"]["token"], list) and not all(token == "" for token in cfg["bot"]["token"]):
                def first_token():
                    for t in cfg["bot"]["token"]:
                        if t != "":
                            return t
                await self.bot.start(first_token())
            else:
                terminal.log("CRITICAL", f"No token was provided in '{utils.config.CONFIG_PATH}'")
        except Exception as e:
            self.statusbar.showMessage(str(e))
    else:
        self.statusbar.showMessage("Stopping Bot...")
        await self.bot.close()
        self.plainTextEdit_botTerminal.clear()
        while not self.bot.is_closed():
            # 避免空转占用CPU,添加短延迟
            await asyncio.sleep(0.1)
        if self.bot.is_closed():
            print("Closed")
            self.statusbar.showMessage("Bot Has Been Stopped...")
            self.pushButton_startBot.setText("Start Bot")
            self.isBotRunning = False
            await asyncio.sleep(1)
            self.pushButton_startBot.setEnabled(True)

方案2:手动重置原有Bot实例内部状态(纯hack方案)

如果不想每次重复注册命令、事件,可以手动重置Bot实例的私有属性恢复启动能力,注意该方案依赖discord.py的内部实现,版本更新后可能失效:
在确认Bot完全关闭后,执行以下重置代码,之后就可以直接调用bot.start()重新启动:

# 确认bot.is_closed()返回True后执行
import asyncio
# 重置关闭标记
bot._closed = False
# 重置就绪事件
bot._ready = asyncio.Event()
# 重置HTTP会话
if hasattr(bot, 'http'):
    bot.http.renew_session()
# discord.py v2.x版本需要额外加这行重置网关连接
bot._connection = bot._get_connection()

另外你原有代码中等待Bot关闭的循环是空转,建议添加await asyncio.sleep(0.1)的短延迟避免占用过多CPU资源。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 01:12:01