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

Discord.py v2.0按钮交互调用interaction属性触发AttributeError

解决Discord.py 2.0按钮回调中AttributeError: 'Button' object has no attribute 'user'问题

问题描述

使用Discord.py 2.0开发带按钮功能的Discord机器人时,调用interaction.user、interaction.response等任意interaction相关属性,都会触发错误:AttributeError: 'Button' object has no attribute 'user'。

报错回溯

Traceback (most recent call last):
  File "C:\Users\parke\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\discord\ui\view.py", line 423, in _scheduled_task
    await item.callback(interaction)
  File "C:\Users\parke\Documents\GitHub\thedrew\goblins\goblin.py", line 29, in menu1
    print(f'added {interaction.user.name} to party')
AttributeError: 'Button' object has no attribute 'user'

完整代码

import discord
from discord.ext import commands

client = commands.Bot(command_prefix='g!', intents=discord.Intents.all())

inProgress = False
combat = []
turn = False


class Player:
    hp = 100
    atk = 100

player1 = Player()
player2 = Player()

@client.event
async def on_ready():
    print('ready to battle')


class Invite(discord.ui.View):
    def __init__(self):
        super().__init__()

    @discord.ui.button(label="Accept", style=discord.ButtonStyle.green)
    async def menu1(self, button: discord.ui.Button, interaction: discord.Interaction):
        print(f'added {interaction.user.name} to party')
        combat.append(interaction.user)

    @discord.ui.button(label="Decline", style=discord.ButtonStyle.red)
    async def menu2(self, button: discord.ui.Button, interaction: discord.Interaction):
        print(f'{interaction.user} declined invitation')
        combat.clear()


@client.command()
async def invite(ctx, member: discord.Member):
    em = discord.Embed(title=f'Goblin Combat Invite', description=f"You've been invited to Goblin Combat by {ctx.author.name}!")

    view = Invite()
    await ctx.channel.send(embed=em, view=view)
    print(f'Invited {member.name} to Goblin Combat!')


@client.command()
async def start(ctx):
    global inProgress
    if ctx.author in combat and inProgress == False:
        await gameLoop(ctx)
    elif inProgress == True:
        await ctx.channel.send('Someone has already been challenged to Goblin Combat. Sit back and enjoy the show!')
    elif ctx.author not in combat:
        await ctx.channel.send('You have not been invited to Goblin Combat. Sucks to be you!')


class Actions(discord.ui.View):
    def __init__(self):
        super().__init__()

    @discord.ui.button(label="Attack", style=discord.ButtonStyle.red)
    async def menu1(self, button: discord.ui.Button, interaction: discord.Interaction):
        print(f'did {player1.atk} damage')
        await interaction.message.channel.send(f'{interaction.user.name} attacked for {player1.atk} damage!')

    @discord.ui.button(label="Use", style=discord.ButtonStyle.green)
    async def menu2(self, button: discord.ui.Button, interaction: discord.Interaction):
        await interaction.response.edit_message(content="Used Goblin Spell")


async def gameLoop(ctx):
    global inProgress
    em = discord.Embed(title=f"Goblin Combat", description=f'{combat[0].name} v {combat[1].name}',
                        color=discord.colour.Color.green())
    em.set_image(url="https://cdn.discordapp.com/attachments/945053385953005648/1000583183017975878/screen.png")
    em.set_footer(text=f"{combat[int(turn)].name}'s Turn")

    view = Actions()

    await ctx.channel.send(embed=em, view=view)
    inProgress = True

client.run(token)

解决方案

这个错误的核心是按钮回调函数的参数顺序搞反了。在Discord.py 2.0中,按钮回调的正确参数顺序是:interaction: discord.Interaction在前,button: discord.ui.Button在后。

你当前的回调函数写法把参数顺序写反了,导致代码里的interaction变量实际接收的是Button实例,自然不存在user属性。只需修正所有按钮回调的参数顺序即可:

修正Invite类的按钮回调

@discord.ui.button(label="Accept", style=discord.ButtonStyle.green)
async def menu1(self, interaction: discord.Interaction, button: discord.ui.Button):
    print(f'added {interaction.user.name} to party')
    combat.append(interaction.user)

@discord.ui.button(label="Decline", style=discord.ButtonStyle.red)
async def menu2(self, interaction: discord.Interaction, button: discord.ui.Button):
    print(f'{interaction.user} declined invitation')
    combat.clear()

修正Actions类的按钮回调

@discord.ui.button(label="Attack", style=discord.ButtonStyle.red)
async def menu1(self, interaction: discord.Interaction, button: discord.ui.Button):
    print(f'did {player1.atk} damage')
    await interaction.message.channel.send(f'{interaction.user.name} attacked for {player1.atk} damage!')

@discord.ui.button(label="Use", style=discord.ButtonStyle.green)
async def menu2(self, interaction: discord.Interaction, button: discord.ui.Button):
    await interaction.response.edit_message(content="Used Goblin Spell")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 19:24:19