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

discord.py中列表append操作失效问题求助

问题排查与修复方案

兄弟,你遇到的核心问题太明显了——每次触发.spam命令时,你都在重新创建一个新列表,直接把之前存的服务器ID覆盖了,自然不会追加新ID!下面我一步步给你拆解问题,再给出完整的修复代码。

1. 列表覆盖的根源

看你on_message里这段代码:

if message.content.startswith('.spam'):
    global thislist
    thislist = [message.guild.id]

每次收到.spam消息,你都用thislist = [message.guild.id]创建了一个全新的列表,之前的内容直接被丢弃。正确的做法是先初始化一次列表,然后用append()添加新ID。

2. 修复列表追加逻辑

首先把列表初始化移到全局作用域(只在bot启动时执行一次),然后在.spam触发时判断ID是否已存在,不存在就追加:

# 全局初始化存储服务器ID的列表,只执行一次
running_guilds = []

# 然后修改on_message里的.spam处理:
if message.content.startswith('.spam'):
    guild_id = message.guild.id
    if guild_id not in running_guilds:
        running_guilds.append(guild_id)
    print(running_guilds)
    print(len(running_guilds))

3. 修复多服务器冲突的stop逻辑

你原来用全局变量s和z来控制停止,这在多服务器场景下会炸锅——比如A服务器执行stop,会把B服务器的spam也停了。改用字典按服务器ID单独控制状态才是正确的:

# 全局字典,键是服务器ID,值是是否停止spam
spam_status = {}

# 修改on_message里的.stop处理:
if message.content.startswith('.stop'):
    guild_id = message.guild.id
    spam_status[guild_id] = True

# 然后修改spam命令的循环逻辑:
@client.command()
@commands.has_role('discordpy')
async def spam(ctx, *, my_id):
    print("it worked")
    await asyncio.sleep(5)  # 这里必须替换time.sleep,不然会阻塞整个bot
    x = 1
    guild_id = ctx.guild.id
    spam_status[guild_id] = False  # 标记当前服务器spam为运行中
    while not spam_status.get(guild_id, False):
        myid = str(my_id)
        await ctx.channel.send(f"{myid} x {x}")
        print(x)
        x += 1
        await asyncio.sleep(0.5)  # 同样替换time.sleep

4. 修复stopbot命令的错误

你原来的self.isrunning = False完全没用,应该用client.close()来关闭bot:

@client.command()
@commands.has_role('discordpy')
async def stopbot(ctx):
    await ctx.send("Bot正在关闭...")
    await client.close()

完整修复后的代码

整合所有修改,还优化了变量名让代码更易懂:

import discord, pyautogui, asyncio
from discord.ext import commands

client = commands.Bot(command_prefix = '.')
# 存储正在运行spam的服务器ID
running_guilds = []
# 存储每个服务器的spam停止状态
spam_status = {}

@client.event
async def on_ready():
    print('We have logged in as {0.user}'.format(client))

@client.event
async def on_message(message):
    if message.author == client.user:
        return
    if message.content.startswith('.spam'):
        guild_id = message.guild.id
        if guild_id not in running_guilds:
            running_guilds.append(guild_id)
        print(running_guilds)
        print(len(running_guilds))
    if message.content.startswith('.stop'):
        guild_id = message.guild.id
        spam_status[guild_id] = True
    await client.process_commands(message)

@client.command()
@commands.has_role('discordpy')
async def spam(ctx, *, my_id):
    print("it worked")
    await asyncio.sleep(5)
    x = 1
    guild_id = ctx.guild.id
    spam_status[guild_id] = False
    if guild_id not in running_guilds:
        running_guilds.append(guild_id)
    while not spam_status.get(guild_id, False):
        myid = str(my_id)
        await ctx.channel.send(f"{myid} x {x}")
        print(x)
        x += 1
        await asyncio.sleep(0.5)
    # 停止后从运行列表移除
    if guild_id in running_guilds:
        running_guilds.remove(guild_id)

@client.command()
@commands.has_role('discordpy')
async def stop(ctx):
    guild_id = ctx.guild.id
    spam_status[guild_id] = True
    await ctx.send("Spam已停止!")
    if guild_id in running_guilds:
        running_guilds.remove(guild_id)

@client.command()
@commands.has_role('discordpy')
async def stopbot(ctx):
    await ctx.send("Bot正在关闭...")
    await client.close()

client.run('你的Token')

重要提醒

  • 绝对不要用time.sleep()在discord.py的异步代码里!它会阻塞整个bot的事件循环,导致bot无法响应任何消息和命令,必须用asyncio.sleep()代替。
  • 全局变量要谨慎使用,像多服务器场景下,用字典按服务器ID隔离状态才不会出冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 21:12:31