
本文详解 discord.py 2.3+ 中 Slash 命令的正确实现方式,包括 CommandTree 的使用、命令注册、同步机制及常见错误规避,帮助开发者告别 ImportError: cannot import 'SlashCommand'。
本文详解 discord.py 2.3+ 中 slash 命令的正确实现方式,包括 commandtree 的使用、命令注册、同步机制及常见错误规避,帮助开发者告别 `importerror: cannot import 'slashcommand'`。
Discord.py 自 2.0 版本起彻底重构了应用命令(即 Slash 命令)的支持机制:不再提供 SlashCommand 类,也不支持手动实例化命令对象。你遇到的 Import Error: cannot import 'SlashCommand' from 'discord.app_commands' 正是因为该类根本不存在于当前版本的 discord.py 中——它属于过时的第三方库或早期非官方实现,与官方 discord.py 2.x 的设计范式完全不符。
✅ 正确做法是使用内置的 app_commands.CommandTree(通常通过 Bot.tree 访问),配合装饰器 @tree.command() 或 @bot.tree.command() 注册命令。以下是重构后的完整、可运行的 /mute 示例:
import discord
from discord.ext import commands
from discord import app_commands
# 推荐使用 commands.Bot 而非 raw Client —— 它内置 CommandTree 并简化事件管理
intents = discord.Intents.default()
intents.message_content = True
intents.members = True # 需要获取 member.top_role 和检查权限
bot = commands.Bot(command_prefix="!", intents=intents)
# ✅ 正确注册 Slash 命令:使用 bot.tree.command()
@bot.tree.command(name="mute", description="Mutes a member for a specific reason.")
@app_commands.describe(
member="The member to mute",
reason="Optional reason for muting"
)
async def mute(interaction: discord.Interaction, member: discord.Member, reason: str = None):
# 权限检查:执行者需有管理角色权限
if not interaction.user.guild_permissions.manage_roles:
await interaction.response.send_message("❌ You lack `Manage Roles` permission.", ephemeral=True)
return
# 权限检查:Bot 自身需能管理目标成员(角色层级)
if member.top_role >= interaction.guild.me.top_role:
await interaction.response.send_message("❌ I cannot mute users with equal or higher roles.", ephemeral=True)
return
# 查找或创建 "Muted" 角色
muted_role = discord.utils.get(interaction.guild.roles, name="Muted")
if not muted_role:
try:
muted_role = await interaction.guild.create_role(
name="Muted",
permissions=discord.Permissions(send_messages=False, speak=False),
reason="Auto-created for mute functionality"
)
# 将角色置于底部(确保不影响其他权限),或手动调整位置
await muted_role.edit(position=1)
except discord.Forbidden:
await interaction.response.send_message("❌ Failed to create `Muted` role. Check my role position and permissions.", ephemeral=True)
return
# 执行静音:添加角色
try:
await member.add_roles(muted_role, reason=reason or "No reason provided")
await interaction.response.send_message(f"✅ {member.mention} has been muted.", ephemeral=False)
# 可选:私信通知被静音用户
if reason:
try:
await member.send(f"You were muted in **{interaction.guild.name}** for: {reason}")
except discord.Forbidden:
pass # 用户关闭了私信
except discord.Forbidden:
await interaction.response.send_message("❌ Failed to assign `Muted` role. Please check my role hierarchy and permissions.", ephemeral=True)
# ✅ 同步命令:避免在 on_ready 中直接调用 sync()(易因网关未就绪失败)
@bot.command()
@commands.is_owner()
async def sync(ctx: commands.Context):
try:
synced = await bot.tree.sync()
await ctx.send(f"✅ Synced {len(synced)} application command(s).")
except Exception as e:
await ctx.send(f"❌ Sync failed: {e}")
# ❌ 不推荐:on_ready 中 sync(可能触发 400 Bad Request 或超时)
# @bot.event
# async def on_ready():
# await bot.tree.sync() # ⚠️ 不稳定,尤其在多服务器环境下
# print(f'Logged in as {bot.user}')
bot.run("YOUR_BOT_TOKEN") # 替换为你的 token
? 关键注意事项:
- 不要使用 Client + 手动 SlashCommand 实例:discord.Client 不自带 tree 属性,且 SlashCommand 类从未存在于官方 discord.py 中。
- 务必使用 commands.Bot:它自动初始化 CommandTree,并提供更完善的命令生命周期管理。
- 同步不是一次性操作:每次修改命令(如改名、加参数、删命令)后都需重新 sync();生产环境建议搭配 /sync 管理命令。
- 权限与角色层级:member.top_role >= interaction.guild.me.top_role 是判断 Bot 是否有权操作的关键逻辑,不可省略。
- ephemeral=True:对敏感操作(如权限检查失败)使用临时响应,避免暴露给全体成员。
- 错误处理必须显式:网络请求、角色创建、DM 发送均可能失败,应 try/except 捕获 discord.Forbidden、discord.HTTPException 等。
? 最后提醒:官方文档始终是权威来源——请优先查阅 discord.py App Commands 文档 及 examples/app_commands 中的实战示例。摒弃过时教程中“手动构建 SlashCommand”的思路,拥抱 CommandTree 这一现代、稳定、可扩展的设计模式。











