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

Discord Bot开发:无法从discord导入Select的错误求助

Discord Bot 导入错误:无法从 'discord' 导入 'Select'

错误信息

Traceback (most recent call last):
  File "c:\Users\name\Desktop\Discord\main.py", line 4, in <module>
    from discord import Select, SelectOption, ActionRow
ImportError: cannot import name 'Select' from 'discord'

问题背景

中断编程半年后,之前能正常运行的Discord Bot代码出现上述导入错误,尝试多种网络方法耗时2小时仍未解决,现寻求技术支持。完整代码如下:

import discord
from discord.ext import commands
from discord import Select, SelectOption, ActionRow

intents = discord.Intents.default()
intents.members = True
intents.message_content = True

bot = commands.Bot(command_prefix='!', intents=intents)

intents.typing = False
intents.presences = False

users = {}

@bot.event
async def on_ready():
    print(f'Вошел в систему как {bot.user}')

@bot.command()
async def start(ctx):
    user_id = ctx.author.id
    if user_id not in users:
        users[user_id] = {
            'games': 0,
            'currency': 0
        }
        embed = discord.Embed(
            title="Успешная регистрация",
            description="Вы успешно зарегистрировались!",
            color=discord.Color.green()
        )
        await ctx.send(embed=embed)
    else:
        embed = discord.Embed(
            title="Регистрация не удалась",
            description="Вы уже зарегистрированы!",
            color=discord.Color.red()
        )
        await ctx.send(embed=embed)

@bot.command()
async def играть(ctx):
    options = [
        SelectOption(label="Угадай число", value="option1"),
        SelectOption(label="Option 2", value="option2"),
        SelectOption(label="Option 3", value="option3"),
    ]

    select = Select(custom_id="select_menu", placeholder="Выберите опцию", options=options)

    action_row = ActionRow(select)

    await ctx.send("Пожалуйста, выберите опцию:", components=[action_row])

@bot.event
async def on_select_option(interaction: discord.Interaction):
    if interaction.custom_id == "select_menu":
        selected_value = interaction.data["values"][0]
        await interaction.response.send_message(f"Вы выбрали: {selected_value}", ephemeral=True)

@bot.command()
@commands.has_role('Chapter [10]')
async def money(ctx, action, user: discord.Member, amount: int):
    user_id = user.id
    if user_id in users:
        if action == 'выдать':
            users[user_id]['currency'] += amount
            await ctx.send(f'Вы выдали {amount} валюты пользователю {user.name}')
        elif action == 'забрать':
            if users[user_id]['currency'] >= amount:
                users[user_id]['currency'] -= amount
                await ctx.send(f'Вы забрали {amount} валюты у пользователя {user.name}')
            else:
                await ctx.send('У пользователя недостаточно валюты!')
        else:
            await ctx.send('Недопустимое действие!')
    else:
        await ctx.send('Пользователь не зарегистрирован!')

@bot.command()
async def info(ctx):
    user_id = ctx.author.id
    if user_id in users:
        games = users[user_id]['games']
        currency = users[user_id]['currency']
        registration_date = users[user_id]['registration_date']
        embed = discord.Embed(title='Статистика', color=discord.Color.blue())
        embed.add_field(name='Количество игр', value=games, inline=False)
        embed.add_field(name='Количество валюты', value=currency, inline=False)
        embed.add_field(name='Дата регистрации', value=registration_date, inline=False)
        await ctx.send(embed=embed)
    else:
        await ctx.send('Вы не зарегистрированы!')

bot.run('TOKEN')

解决方案

核心问题

你之前使用的Discord.py版本较旧,现在Discord.py版本更新后,Select、SelectOption、ActionRow这些组件已从discord根模块移至discord.ui子模块,同时旧版的on_select_option事件已被废弃。

具体修改步骤

  1. 修正导入路径
    将代码中的导入语句:

    from discord import Select, SelectOption, ActionRow
    

    替换为:

    from discord.ui import Select, SelectOption, ActionRow
    
  2. 重构交互事件处理
    旧版的on_select_option事件不再生效,改用组件绑定回调的方式处理选择交互。修改играть命令如下,同时删除原有的on_select_option事件函数:

    @bot.command()
    async def играть(ctx):
        # 定义选择菜单的回调函数
        async def select_callback(interaction: discord.Interaction):
            selected_value = interaction.data["values"][0]
            await interaction.response.send_message(f"Вы выбрали: {selected_value}", ephemeral=True)
    
        options = [
            SelectOption(label="Угадай число", value="option1"),
            SelectOption(label="Option 2", value="option2"),
            SelectOption(label="Option 3", value="option3"),
        ]
    
        select = Select(custom_id="select_menu", placeholder="Выберите опцию", options=options)
        select.callback = select_callback  # 为选择菜单绑定回调
    
        action_row = ActionRow(select)
        await ctx.send("Пожалуйста, выберите опцию:", components=[action_row])
    
  3. 修复代码遗漏问题
    原代码中info命令调用了registration_date但start命令未初始化该字段,需要在start命令的用户字典中添加:

    users[user_id] = {
        'games': 0,
        'currency': 0,
        'registration_date': ctx.message.created_at.strftime("%Y-%m-%d %H:%M:%S")
    }
    
  4. 更新Discord.py到最新版本(可选但推荐)
    打开命令提示符执行以下命令,确保依赖版本兼容:

    pip install -U discord.py
    

修改后的完整可运行代码

import discord
from discord.ext import commands
from discord.ui import Select, SelectOption, ActionRow

intents = discord.Intents.default()
intents.members = True
intents.message_content = True

bot = commands.Bot(command_prefix='!', intents=intents)

intents.typing = False
intents.presences = False

users = {}

@bot.event
async def on_ready():
    print(f'Вошел в систему как {bot.user}')

@bot.command()
async def start(ctx):
    user_id = ctx.author.id
    if user_id not in users:
        users[user_id] = {
            'games': 0,
            'currency': 0,
            'registration_date': ctx.message.created_at.strftime("%Y-%m-%d %H:%M:%S")
        }
        embed = discord.Embed(
            title="Успешная регистрация",
            description="Вы успешно зарегистрировались!",
            color=discord.Color.green()
        )
        await ctx.send(embed=embed)
    else:
        embed = discord.Embed(
            title="Регистрация не удалась",
            description="Вы уже зарегистрированы!",
            color=discord.Color.red()
        )
        await ctx.send(embed=embed)

@bot.command()
async def играть(ctx):
    async def select_callback(interaction: discord.Interaction):
        selected_value = interaction.data["values"][0]
        await interaction.response.send_message(f"Вы выбрали: {selected_value}", ephemeral=True)

    options = [
        SelectOption(label="Угадай число", value="option1"),
        SelectOption(label="Option 2", value="option2"),
        SelectOption(label="Option 3", value="option3"),
    ]

    select = Select(custom_id="select_menu", placeholder="Выберите опцию", options=options)
    select.callback = select_callback

    action_row = ActionRow(select)
    await ctx.send("Пожалуйста, выберите опцию:", components=[action_row])

@bot.command()
@commands.has_role('Chapter [10]')
async def money(ctx, action, user: discord.Member, amount: int):
    user_id = user.id
    if user_id in users:
        if action == 'выдать':
            users[user_id]['currency'] += amount
            await ctx.send(f'Вы выдали {amount} валюты пользователю {user.name}')
        elif action == 'забрать':
            if users[user_id]['currency'] >= amount:
                users[user_id]['currency'] -= amount
                await ctx.send(f'Вы забрали {amount} валюты у пользователя {user.name}')
            else:
                await ctx.send('У пользователя недостаточно валюты!')
        else:
            await ctx.send('Недопустимое действие!')
    else:
        await ctx.send('Пользователь не зарегистрирован!')

@bot.command()
async def info(ctx):
    user_id = ctx.author.id
    if user_id in users:
        games = users[user_id]['games']
        currency = users[user_id]['currency']
        registration_date = users[user_id]['registration_date']
        embed = discord.Embed(title='Статистика', color=discord.Color.blue())
        embed.add_field(name='Количество игр', value=games, inline=False)
        embed.add_field(name='Количество валюты', value=currency, inline=False)
        embed.add_field(name='Дата регистрации', value=registration_date, inline=False)
        await ctx.send(embed=embed)
    else:
        await ctx.send('Вы не зарегистрированы!')

bot.run('TOKEN')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 19:20:56