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

Python UnboundLocalError问题求助(Discord游戏工具开发)

问题:UnboundLocalError: cannot access local variable 'initial_data' where it is not associated with a value

开发本地Discord工具,从osu! API获取数据并存储为JSON,再通过Python函数将值存入元组,调用功能时触发上述错误。

报错栈信息

Traceback (most recent call last):
  File "/var/lib/pufferpanel/servers/bd502203/.local/lib/python3.11/site-packages/discord/app_commands/commands.py", line 862, in _do_call
    return await self._callback(interaction, **params)  # type: ignore
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/var/lib/pufferpanel/servers/bd502203/scoreposter.py", line 251, in scoreposter
    await interaction.response.send_message(f"```{scorepost(osu_user,mode , False)}```", ephemeral=False)
                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/var/lib/pufferpanel/servers/bd502203/scoreposter.py", line 168, in scorepost
    beatmap_id, rank, score_max, n300, n100, n50, nmiss, perfect, int_mods, score_id = extract_initial_data(initial_data)
                                                                                                            ^^^^^^^^^^^^
UnboundLocalError: cannot access local variable 'initial_data' where it is not associated with a value

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/var/lib/pufferpanel/servers/bd502203/.local/lib/python3.11/site-packages/discord/app_commands/tree.py", line 1242, in _call
    await command._invoke_with_namespace(interaction, namespace)
  File "/var/lib/pufferpanel/servers/bd502203/.local/lib/python3.11/site-packages/discord/app_commands/commands.py", line 887, in _invoke_with_namespace
    return await self._do_call(interaction, transformed_values)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/var/lib/pufferpanel/servers/bd502203/.local/lib/python3.11/site-packages/discord/app_commands/commands.py", line 880, in _do_call
    raise CommandInvokeError(self, e) from e
discord.app_commands.errors.CommandInvokeError: Command 'scorepost' raised an exception: UnboundLocalError: cannot access local variable 'initial_data' where it is not associated with a value

相关代码片段

工具函数部分

def int_to_santised_int(value: int) -> int:
    if value == 0:
        return 0
    else:
        mods_to_check = [1024, 512, 256, 64, 16, 8, 2] # FL, NC, HT, DT, HR, HD, EZ
        combined_value = 0
        for mod in mods_to_check:
            if value & mod:
                combined_value |= mod
        return combined_value

def extract_initial_data(initial_data):
    try:
        beatmap_id, rank, score_max, n300, n100, n50, nmiss, perfect, int_mods, score_id = (
            initial_data[0]["beatmap_id"], 
            initial_data[0]["rank"],
            int(initial_data[0]["maxcombo"]), 
            int(initial_data[0]["count300"]), 
            int(initial_data[0]["count100"]), 
            int(initial_data[0]["count50"]), 
            int(initial_data[0]["countmiss"]), 
            initial_data[0]["perfect"], 
            int_to_santised_int(int(initial_data[0]["enabled_mods"])),
            initial_data[0]["score_id"]
        )
    except IndexError as e:
        print(f"an exception occurred: '{e}'; that user probably doesn't have any data available.")
        raise
    return beatmap_id, rank, score_max, n300, n100, n50, nmiss, perfect, int_mods, score_id

核心功能函数

def scorepost(username : str, link : bool, mode : str):
 # make a request to the osu! API to retrieve the user's most recent play
    if link == False:
        try:
            print(f"making initial score request for {username}...")
            inital_response_user = requests.get(f"https://osu.ppy.sh/api/get_user_recent?k={osu_api_key}&u={username}&m={gamemode}&limit=1")
            print(inital_response_user)
        except:
            return "No plays done by that player recently"
        else:
            # parse the response as JSON
            initial_data = inital_response_user.json()

    beatmap_id, rank, score_max, n300, n100, n50, nmiss, perfect, int_mods, score_id = extract_initial_data(initial_data)

解决方案

核心问题分析

  1. 参数顺序不匹配:调用scorepost时的参数顺序与函数定义不一致,导致link参数未接收到预期的False值,无法进入API请求逻辑,initial_data未被定义。
  2. 分支覆盖不全:当link != False时,没有为initial_data赋值的逻辑,直接调用extract_initial_data必然触发未定义错误。
  3. 拼写错误隐患:inital_response_user存在拼写错误(应为initial_response_user),虽当前不影响运行,但易引发后续维护问题。

修复步骤

  1. 修正参数调用顺序
    原调用代码将mode和False的顺序传反,需调整为函数定义的username, link, mode顺序:

    # 原调用
    # await interaction.response.send_message(f"```{scorepost(osu_user,mode , False)}```", ephemeral=False)
    # 修改后
    await interaction.response.send_message(f"```{scorepost(osu_user, False, mode)}```", ephemeral=False)
    
  2. 完善分支逻辑,确保initial_data始终被定义
    在函数开头初始化initial_data为默认值,并补充link == True时的处理逻辑,避免未定义:

    def scorepost(username : str, link : bool, mode : str):
        initial_data = []  # 初始化默认值
        if link == False:
            try:
                print(f"making initial score request for {username}...")
                # 修正拼写错误
                initial_response_user = requests.get(f"https://osu.ppy.sh/api/get_user_recent?k={osu_api_key}&u={username}&m={gamemode}&limit=1")
                print(initial_response_user)
            except Exception as e:
                print(f"API请求失败: {str(e)}")
                return "No plays done by that player recently"
            else:
                initial_data = initial_response_user.json()
        else:
            # 补充link为True时的数据获取逻辑,例如从链接解析数据
            # 示例:initial_data = parse_link_data(link)
            pass
    
        # 调用前检查数据有效性
        if not initial_data:
            return "No valid play data found"
        beatmap_id, rank, score_max, n300, n100, n50, nmiss, perfect, int_mods, score_id = extract_initial_data(initial_data)
        # 后续业务逻辑...
    
  3. 修正拼写错误
    将inital_response_user统一改为initial_response_user,保持变量名拼写一致,降低维护风险。

  4. 增强异常处理
    在extract_initial_data中添加空数据检查和KeyError捕获,提前处理无效数据:

    def extract_initial_data(initial_data):
        if not initial_data:
            raise ValueError("No play data available")
        try:
            beatmap_id, rank, score_max, n300, n100, n50, nmiss, perfect, int_mods, score_id = (
                initial_data[0]["beatmap_id"], 
                initial_data[0]["rank"],
                int(initial_data[0]["maxcombo"]), 
                int(initial_data[0]["count300"]), 
                int(initial_data[0]["count100"]), 
                int(initial_data[0]["count50"]), 
                int(initial_data[0]["countmiss"]), 
                initial_data[0]["perfect"], 
                int_to_santised_int(int(initial_data[0]["enabled_mods"])),
                initial_data[0]["score_id"]
            )
        except IndexError as e:
            print(f"an exception occurred: '{e}'; that user probably doesn't have any data available.")
            raise
        except KeyError as e:
            print(f"Missing expected data field: {e}")
            raise
        return beatmap_id, rank, score_max, n300, n100, n50, nmiss, perfect, int_mods, score_id
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 20:40:17