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

discord.py中on_message()变量识别异常及重置问题求助

解决discord.py on_message中变量重置与未定义问题的几种方法

我完全理解你不想放弃熟悉的on_message机制重写脚本的心情,毕竟用顺手的东西换起来确实麻烦。针对你遇到的两个核心问题——全局变量在函数内修改报错、局部变量每次触发都重置,这里有几个不用切换到commands框架的解决方案:

方法一:用global关键字绑定全局变量

这是最直接的解决方式,只要在on_message里声明你要修改的变量是全局的,Python就不会把它当成局部变量处理,自然也不会出现UnboundLocalError,而且全局变量只会初始化一次,不会每次触发消息就重置。

示例代码:

import discord
client = discord.Client()
token = "your_token_here"
prefix = "!"  # 初始前缀定义在全局

@client.event
async def on_message(message):
    global prefix  # 声明要使用全局的prefix变量,必须写在修改之前
    if message.author == client.user:
        return
    
    # 修改前缀的命令逻辑
    if message.content.startswith(prefix + "changeprefix"):
        # 这里假设命令格式是「原前缀 changeprefix 新前缀」
        try:
            new_prefix = message.content.split()[1]
            prefix = new_prefix
            await message.channel.send(f"前缀已成功修改为:{prefix}")
        except IndexError:
            await message.channel.send("请指定要修改的新前缀!")
    
    # 测试用的hello命令
    if message.content.startswith(prefix + "hello"):
        await message.channel.send(f"哈喽!当前前缀是{prefix}")

client.run(token)

方法二:将变量绑定到client实例的属性上

如果你不想用global关键字(毕竟有些开发者觉得global不够优雅),可以把需要持久化的变量挂载到client对象上。client是全局唯一的实例,它的属性会一直存在到机器人停止运行,不会每次触发on_message就重置。

示例代码:

import discord
client = discord.Client()
token = "your_token_here"
client.prefix = "!"  # 把前缀作为client的自定义属性

@client.event
async def on_message(message):
    if message.author == client.user:
        return
    
    if message.content.startswith(client.prefix + "changeprefix"):
        try:
            new_prefix = message.content.split()[1]
            client.prefix = new_prefix
            await message.channel.send(f"前缀已成功修改为:{client.prefix}")
        except IndexError:
            await message.channel.send("请指定要修改的新前缀!")
    
    if message.content.startswith(client.prefix + "hello"):
        await message.channel.send(f"哈喽!当前前缀是{client.prefix}")

client.run(token)

方法三:持久化存储(适合需要重启后保留设置的场景)

上面两种方法都有个小缺点:机器人重启后,修改过的前缀会回到初始值。如果你希望修改的设置能在重启后保留,可以用文件或者数据库来存储变量值,每次启动时读取,修改时写入。

示例代码(用txt文件存储):

import discord

client = discord.Client()
token = "your_token_here"

# 加载前缀的函数:优先读文件,没有文件就创建并写入默认前缀
def load_prefix():
    try:
        with open("prefix_storage.txt", "r", encoding="utf-8") as f:
            return f.read().strip()
    except FileNotFoundError:
        with open("prefix_storage.txt", "w", encoding="utf-8") as f:
            f.write("!")
        return "!"

# 启动时加载前缀到client属性
client.prefix = load_prefix()

@client.event
async def on_message(message):
    if message.author == client.user:
        return
    
    if message.content.startswith(client.prefix + "changeprefix"):
        try:
            new_prefix = message.content.split()[1]
            client.prefix = new_prefix
            # 修改后写入文件
            with open("prefix_storage.txt", "w", encoding="utf-8") as f:
                f.write(new_prefix)
            await message.channel.send(f"前缀已成功修改为:{client.prefix}")
        except IndexError:
            await message.channel.send("请指定要修改的新前缀!")
    
    if message.content.startswith(client.prefix + "hello"):
        await message.channel.send(f"哈喽!当前前缀是{client.prefix}")

client.run(token)

这三种方法都不需要你放弃on_message机制,直接在现有脚本基础上修改就行。前两种适合不需要持久化的场景,第三种适合需要保留设置的情况,你可以根据自己的需求选择~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:50:43