Discord.py机器人启动4分钟后按钮失效的解决办法咨询
Discord机器人按钮4分钟后失效的修复方案
问题描述
使用Python的discord.py开发Discord机器人,机器人启动4分钟后按钮会停止工作,原本打算每3分钟重启机器人,寻求其他修复方案。
当前代码情况
导入的库
import discord from random import randint import json from discord.ext import commands # 注意:此处导入错误,正确应为 from discord.ui import Button, View from discord.User interface import button, view
按钮示例代码
class ButtonSandStone8(discord.ui.Button): def __init__(self, label): super().__init__(label=label, style=discord.ButtonStyle.grey, custom_id='SandStone_btn8') async def callback(self, interaction): global queue8 if f"<@{interaction.user.id}>\n\n\n" in queue8: global lobby_voice8, ct8, t8, voice_ct8, voice_t8 voice_state = interaction.user.voice if voice_state is None: embed = discord.Embed(description='你必须进入语音频道才能参与!', color=discord.Color.dark_grey()) return await interaction.response.send_message(embed=embed, ephemeral=True) elif interaction.user.voice.channel.id == lobby_voice8: global voices8 if len(queue8)-10 < 10: embed = discord.Embed(description='队列未满!', color=discord.Color.dark_grey()) await interaction.response.send_message(embed=embed, ephemeral=True) elif len(queue8)-10 == 10 and interaction.user not in voices8 and f"<@{interaction.user.id}>\n\n\n" in queue8: voices8.append(interaction.user) global SandStone8, Rust8, Zone98, Province8, Breeze8 SandStone8 += 1 if len(voices8) < 10: embed = discord.Embed(description='+1 票给SandStone地图', color=discord.Color.dark_grey()) await interaction.response.send_message(embed=embed, ephemeral=True) if len(voices8) == 10: global msg8 await msg8.delete() if SandStone8 > Rust8 and SandStone8 > Zone98 and SandStone8 > Breeze8 and SandStone8 > Province8: await distribution_sandstone8(interaction) elif Rust8 > SandStone8 and Rust8 > Zone98 and Rust8 > Breeze8 and Rust8 > Province8: await distribution_rust8(interaction) elif Zone98 > SandStone8 and Zone98 > Rust8 and Zone98 > Province8 and Zone98 > Breeze8: await distribution_zone98(interaction) elif Province8 > SandStone8 and Province8 > Rust8 and Province8 > Zone98 and Province8 > Breeze8: await distribution_province8(interaction) elif Breeze8 > SandStone8 and Breeze8 > Rust8 and Breeze8 > Zone98 and Breeze8 > Province8: await distribution_breeze8(interaction) else: voices8.clear() SandStone8 = 0 Rust8 = 0 Zone98 = 0 Province8 = 0 Breeze8 = 0 embed = discord.Embed(description='平局!重新投票', color=discord.Color.dark_grey()) await interaction.response.send_message(embed=embed, delete_after=180) else: embed = discord.Embed(description='你连接的不是正确的语音频道!', color=discord.Color.dark_grey()) await interaction.response.send_message(embed=embed, ephemeral=True) else: embed = discord.Embed(description='你不在投票队列中!', color=discord.Color.red()) await interaction.response.send_message(embed=embed, ephemeral=True)
按钮调用示例代码
SandStone_btn8 = ButtonSandStone8("1.SandStone") # 修改此处:设置timeout=None避免超时失效 w = discord.ui.View(timeout=None) w.add_item(SandStone_btn8)
修复方案
1. 解决View超时问题
discord.py的View默认超时时间为180秒(3分钟),超时后按钮会自动失效。直接将View的timeout参数设为None,即可让按钮永久有效:
w = discord.ui.View(timeout=None)
2. 修复导入错误
原代码中的导入语句有误,正确的导入方式应为:
from discord.ui import Button, View
错误的导入可能导致视图系统无法正常工作,进而引发按钮失效问题。
3. 使用持久化视图(可选)
如果希望机器人重启后按钮依然能响应,需要注册持久化视图。在机器人启动时添加以下代码:
# 在机器人启动完成后注册持久化视图 @bot.event async def on_ready(): bot.add_view(ButtonSandStone8(label="1.SandStone")) print(f"Logged in as {bot.user}")
注意:持久化视图要求按钮必须设置唯一的custom_id(你的代码中已经设置了custom_id='SandStone_btn8',符合要求)。
4. 替换全局变量,用类封装状态
代码中大量使用全局变量,容易导致状态混乱和内存泄漏,建议用类来封装每个游戏大厅的状态:
class GameLobby: def __init__(self, lobby_voice_channel): self.lobby_voice = lobby_voice_channel self.queue = [] self.voices = [] # 投票计数 self.votes = { "SandStone": 0, "Rust": 0, "Zone9": 0, "Province": 0, "Breeze": 0 } self.msg = None # 使用示例 lobby8 = GameLobby(lobby_voice_channel)
然后在按钮的callback方法中引用这个类的实例,替代全局变量,避免全局状态污染。
5. 检查交互响应的完整性
确保所有分支都有对应的交互响应,避免因未响应导致Discord标记交互失败,进而影响后续按钮功能。你的代码中大部分分支都有send_message,但要确保没有遗漏的情况。
内容的提问来源于stack exchange,提问作者rar_exe
相关产品推荐
相关产品推荐

