如何在调用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
相关产品推荐
相关产品推荐

