Discord按钮中.wait()与.stop()函数配合失效问题求助
问题解决:Discord按钮点击后无法终止view.wait()循环
核心错误原因
你代码里的interaction:discord.Interaction.stop()是完全错误的语法——这不是调用停止方法,而是试图给变量加类型注解,根本没有执行终止view.wait()的操作。要让await view.wait()结束,必须调用View对象的stop方法,也就是view.stop()。
其他问题及完整修正方案
除了核心错误,你的代码还有几个会导致异常或逻辑问题的点,以下是修正后的代码和对应说明:
修正后的代码
import csv import datetime import discord from discord import ButtonStyle, Button, View from discord.ext import commands @bot.tree.command(name='reminder') async def reminder(interaction: discord.Interaction): # 先延迟响应,避免交互超时 await interaction.response.defer(ephemeral=False) with open("C:/Users/market.csv", "r", newline='') as incsv, open("C:/Users/market2.csv", "w+", newline='') as outcsv: reader = csv.reader(incsv) writer = csv.writer(outcsv) for row in reader: if row[1] == "no": # 每次循环创建新的View和按钮,避免重复添加导致多按钮问题 view = View() # 绑定当前行的副本,解决闭包引用问题 async def buttonyes_callback(interaction: discord.Interaction, row=row.copy()): row[1] = 'yes' writer.writerow(row) await interaction.response.edit_message(content="Offer is canceled", embed=None, view=None) view.stop() # 终止view.wait() async def buttonno_callback(interaction: discord.Interaction, row=row.copy()): writer.writerow(row) await interaction.response.edit_message(content="Offer is still running", embed=None, view=None) view.stop() buttonyes = Button(label="YES", style=ButtonStyle.green, custom_id="1") buttonno = Button(label="NO", style=ButtonStyle.red, custom_id="2") buttonyes.callback = buttonyes_callback buttonno.callback = buttonno_callback view.add_item(buttonyes) view.add_item(buttonno) embed = discord.Embed( title='REMINDER', description=f'Is your {row[2]} over ?', color=65280, timestamp=datetime.datetime.now() ) embed.add_field(name='Model', value=row[3], inline=True) embed.add_field(name='Size', value=row[4], inline=True) embed.add_field(name='Price', value=f"{row[5]}€", inline=True) # 用followup发送消息,因为初始响应已延迟 msg = await interaction.followup.send(embed=embed, view=view, wait=True) await view.wait() else: writer.writerow(row)
关键修改说明
- 修复stop调用:将错误语法改为
view.stop(),这是触发await view.wait()结束的唯一正确方式。 - 每次循环创建新View:避免同一个View被重复添加按钮,导致消息中出现多个相同按钮,同时保证每个提醒的交互独立。
- 延迟初始响应:先调用
await interaction.response.defer(),防止循环处理耗时导致交互超时,后续用followup.send发送每个提醒。 - 解决闭包引用问题:在回调函数中添加
row=row.copy()参数,确保每个回调引用的是当前循环行的副本,不会因为闭包特性引用到最后一行数据。 - 修正重复写入:移除发送消息前的冗余
writer.writerow(row),只在需要时写入数据,避免生成重复行。
额外注意事项
- 如果需要长时间等待用户点击,创建View时可以设置
timeout=None(view = View(timeout=None)),避免超时自动终止。 - 确保机器人拥有发送、编辑消息的权限。
- 处理完成后,
market2.csv会是处理后的结果,可根据需求替换原CSV文件。
内容的提问来源于stack exchange,提问作者Fabar
相关产品推荐
相关产品推荐

