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

在discord.py异步函数中使用外部变量的异常问题

Discord.py每日指令全局变量问题解决方案

问题描述

我正在开发一个discord.py机器人,想要创建/daily指令,但需要在异步函数内部使用外部声明的变量。当前代码如下:

global d
d = 0
@tree.command(name = "daily", description = "Daily sallary.")
async def daily(interaction: discord.Interaction):
    if d == 0:
        await interaction.response.send_message("Yes")
        d = 1
        await asyncio.sleep(86400)
        d = 0
    else:
        await interaction.response.send_message("No")

运行后抛出错误:

UnboundLocalError: cannot access local variable 'd' where it is not associated with a value

尝试修改为以下写法后:

global d
d = 0
@tree.command(name = "daily", description = "Daily sallary.")
async def daily(interaction: discord.Interaction, d=d):
    if d == 0:
        await interaction.response.send_message("Yes")
        d = 1
        await asyncio.sleep(86400)
        d = 0
    else:
        await interaction.response.send_message("No")

依旧报错:

TypeError: parameter 'd' is missing a type annotation in callback 'daily'

解决方法

1. 正确使用全局变量

第一个报错的核心原因是:在函数内部对全局变量d执行赋值操作时,Python会默认将其视为局部变量,但你在赋值前先引用了它,导致变量未绑定的错误。只需在函数内部再次声明global d,明确告知Python使用全局变量即可:

import discord
from discord import app_commands
import asyncio

d = 0  # 全局变量无需在外部加global声明

@app_commands.command(name="daily", description="Daily salary.")
async def daily(interaction: discord.Interaction):
    global d  # 函数内部声明使用全局变量d
    if d == 0:
        await interaction.response.send_message("Yes")
        d = 1
        # 注意:此处sleep会阻塞整个机器人进程,不推荐用于实际场景
        await asyncio.sleep(86400)
        d = 0
    else:
        await interaction.response.send_message("No")

2. 更合理的生产级方案(避免全局变量)

全局变量存在严重缺陷:所有用户共用同一个状态,一个用户领取后其他用户都无法使用,且asyncio.sleep会阻塞整个机器人,期间无法处理其他指令。建议用本地文件或数据库记录每个用户的最后领取时间:

import discord
from discord import app_commands
from datetime import datetime, timedelta
import json

# 用JSON文件存储用户领取记录
USER_DAILY_RECORD = "daily_records.json"

def load_records():
    try:
        with open(USER_DAILY_RECORD, "r") as f:
            return json.load(f)
    except FileNotFoundError:
        return {}

def save_records(data):
    with open(USER_DAILY_RECORD, "w") as f:
        json.dump(data, f)

@app_commands.command(name="daily", description="Daily salary.")
async def daily(interaction: discord.Interaction):
    user_id = str(interaction.user.id)
    records = load_records()
    now = datetime.now()
    
    last_claim_time = records.get(user_id)
    if not last_claim_time or datetime.fromisoformat(last_claim_time) + timedelta(days=1) < now:
        await interaction.response.send_message("Yes,每日奖励领取成功!")
        records[user_id] = now.isoformat()
        save_records(records)
    else:
        next_available = datetime.fromisoformat(last_claim_time) + timedelta(days=1)
        await interaction.response.send_message(f"No,你需要等到{next_available.strftime('%Y-%m-%d %H:%M:%S')}才能再次领取!")

关于第二种写法的错误说明

你尝试给函数参数设置默认值d=d的方式不可行:Discord.py的指令函数参数只能对应指令的可选/必填参数,必须添加类型注解,这种写法会被框架识别为自定义指令参数,而非引用全局变量,因此会抛出类型注解缺失的错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 14:12:40