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

如何让discord.py开发的Discord Bot同时处理多个命令

问题描述

我用discord.py开发了一款Discord机器人,执行/role-all、/backup这类命令时,命令运行期间没法使用其他命令。谷歌搜索过但不知道该用什么关键词,求帮忙解决。


/backup 命令代码(bot.py)

@tree.command(name = "backup", description = "backup the members")
async def backup(interaction: discord.Interaction,limit: int):
    timetowait = limit + 10
    if interaction.user.id == owner:
      await interaction.response.defer()
      count = gettokencount()
      addguild(interaction.guild.id, limit)        
      embed = discord.Embed(title='', description=f"""
**✅ | Members restored**
≡ | restored : {limit}
""", color=5763719)
      await interaction.followup.send(embed=embed)
    else:
        await interaction.response.send_message('you dont have the perms.')

addguild 函数代码

def addguild(guild_id, limit):
  print(guild_id)
  conn = mysql.connector.connect(
      host='localhost',
      database='mydb',
      user='mydbuser',
      password=os.environ.get('databasepass'))

  if conn.is_connected():
      amount = 0
      mycursor = conn.cursor()
      sqli = f"SELECT * FROM ..."
      mycursor.execute(sqli)
      toks = mycursor.fetchall()
      for token in toks:
        rand = random.randint(1,5)
        if amount >= int(limit):
            pass 
        else:
            amount += 1
            id = token[1]
            ref = token[0]
            try:
                tokenObject = client.refresh_token(ref)
                ref_token = tokenObject.refresh_token
                sqlf = f"""UPDATE ...
                          SET refresh_token = '{ref_token}', id = '{id}'
                          WHERE id = '{id}'"""
                mycursor.execute(sqlf)
                conn.commit()
            except: 
                sqlp = f"""DELETE FROM ... WHERE id = '{id}'"""
                mycursor.execute(sqlp)
                conn.commit()
                pass
            try:
                tokenObject.join_guild(guild_id, id)
                time.sleep(rand)
            except Exception:
                amount -= 1
                continue

解决方案

问题核心是同步阻塞操作卡住了异步事件循环。discord.py基于异步IO模型,你的addguild是纯同步函数,里面的time.sleep(rand)、数据库操作、tokenObject.join_guild都是同步阻塞代码,会占用整个事件循环,导致机器人无法处理其他命令请求。

具体修复步骤

  1. 替换同步数据库驱动为异步版本:用aiomysql替代mysql.connector,避免数据库操作阻塞事件循环。
  2. 替换time.sleep为asyncio.sleep:这是异步休眠方法,不会卡住事件循环。
  3. 用线程池处理无法异步的同步操作:如果tokenObject.join_guild这类方法没法改成异步,就用asyncio.to_thread把它放到线程池执行,不占用主事件循环。
  4. 用参数化SQL避免注入风险:之前的字符串拼接SQL写法存在安全隐患,改用占位符传参。

修改后的示例代码

异步版addguild函数

import asyncio
import aiomysql
import random

async def addguild(guild_id, limit):
    print(guild_id)
    conn = await aiomysql.connect(
        host='localhost',
        database='mydb',
        user='mydbuser',
        password=os.environ.get('databasepass')
    )

    if conn:
        amount = 0
        async with conn.cursor() as mycursor:
            await mycursor.execute("SELECT * FROM ...")
            toks = await mycursor.fetchall()
            for token in toks:
                rand = random.randint(1,5)
                if amount >= int(limit):
                    break
                amount += 1
                id = token[1]
                ref = token[0]
                try:
                    # 用线程池包装同步的refresh_token方法
                    tokenObject = await asyncio.to_thread(client.refresh_token, ref)
                    ref_token = tokenObject.refresh_token
                    # 参数化SQL语句
                    await mycursor.execute("""
                        UPDATE ...
                        SET refresh_token = %s, id = %s
                        WHERE id = %s
                    """, (ref_token, id, id))
                    await conn.commit()
                except:
                    await mycursor.execute("DELETE FROM ... WHERE id = %s", (id,))
                    await conn.commit()
                    continue
                try:
                    # 用线程池处理同步的join_guild方法
                    await asyncio.to_thread(tokenObject.join_guild, guild_id, id)
                    await asyncio.sleep(rand)
                except Exception:
                    amount -= 1
                    continue
        await conn.close()

修改后的backup命令

@tree.command(name = "backup", description = "backup the members")
async def backup(interaction: discord.Interaction,limit: int):
    timetowait = limit + 10
    if interaction.user.id == owner:
        await interaction.response.defer()
        count = gettokencount()
        # 调用异步版addguild
        await addguild(interaction.guild.id, limit)        
        embed = discord.Embed(title='', description=f"""
**✅ | Members restored**
≡ | restored : {limit}
""", color=5763719)
        await interaction.followup.send(embed=embed)
    else:
        await interaction.response.send_message('你没有权限。')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 00:01:07