导出MySQL数据为JSON文件时报UnboundLocalError: user_json赋值前引用错误
错误原因
你遇到的UnboundLocalError: local variable 'user_json' referenced before assignment错误,以及代码里隐藏的其他问题可以归纳为以下几点:
- 直接触发报错的逻辑问题:
finally块的特性是无论try块是否执行成功、有没有抛出异常,都会强制执行。如果try块中在user_json = json.dumps(...)这行赋值之前就抛出异常,user_json根本没有被创建,此时finally块里直接读取、打印user_json就会触发「赋值前引用」的错误。 - 代码本身存在多个会导致
try块提前抛错的问题:- 变量名大小写不匹配:函数入参名是
list_user,循环遍历的时候写成了listUser,Python对大小写敏感,这行执行直接抛出NameError,此时还没走到user_json赋值的逻辑 - 未定义的逻辑调用:代码里调用了不存在的
create_dict()方法,且Python原生字典没有.add()方法,这部分逻辑执行直接报错 - 数据遍历逻辑和输入结构不匹配:你提供的测试数据集里每个元素是字典结构,不是下标索引的元组/列表,用
row[0]、row[1]这类下标取值会直接抛出TypeError - 路径依赖问题:硬编码的
.\output\目录如果不存在,写文件时会抛出FileNotFoundError - 逻辑结构错误:
return语句写在finally块中,会覆盖else块的break逻辑,while循环根本无法实现「出错重试」的预期,第一次执行无论成功失败都会直接退出函数。
- 变量名大小写不匹配:函数入参名是
修复方案
修复后可直接运行的完整代码如下:
import json import os from decimal import Decimal # 测试数据集 list_user = [ {'id': 'c9b54584-e70b-11ec-b5e5-02c9dcd6ed1e', 'name': 'Asif', 'age': 25, 'weight': 68, 'height': 170, 'bmi': Decimal('23.53'), 'report': 'Normal'}, {'id': 'c9b571be-e70b-11ec-b5e5-02c9dcd6ed1e', 'name': 'Ema', 'age': 24, 'weight': 52, 'height': 166, 'bmi': Decimal('23.53'), 'report': 'Normal'} ] def func_write_JSON(list_user): # 提前初始化变量,从根源避免赋值前引用的错误 user_json = "" while True: filename = input('please name your file :') # 自动创建输出目录,避免目录不存在报错 output_dir = '.\output' if not os.path.exists(output_dir): os.makedirs(output_dir) filename_txt = os.path.join(output_dir, f'{filename}.json') try: mydict = {} # 匹配输入的字典结构遍历,用key取值替代错误的下标取值 for row in list_user: mydict[row['id']] = { "name": row["name"], "age": row["age"], "weight": row["weight"], "height": row["height"], "bmi": str(row["bmi"]), # Decimal转字符串,解决JSON不支持Decimal序列化的问题 "report": row["report"] } user_json = json.dumps(mydict, indent=2, sort_keys=False) # 写文件指定utf-8编码,避免乱码 with open(filename_txt, 'w', encoding='utf-8') as f: f.write(user_json) except Exception as e: print(f"导出失败:{e},请重试") continue else: print("JSON文件导出成功") break finally: # 仅当有生成内容时打印,避免空值报错 if user_json: print("生成的JSON内容如下:") print(user_json) # return移到循环外,不打断正常重试逻辑 return user_json if __name__ == "__main__": func_write_JSON(list_user)
核心修改点
- 函数入口提前初始化
user_json为空字符串,彻底解决赋值前引用的问题 - 统一变量命名,修正了
listUser的拼写错误 - 移除未定义的
create_dict()调用,直接使用原生字典构造结果,匹配输入数据的字典结构,改用key取值 - 增加输出目录自动创建逻辑,打开文件时指定utf-8编码解决乱码问题
- 调整
return语句位置,移出finally块,保证while循环的出错重试逻辑正常生效 - 增加序列化前的类型处理,把Decimal类型转为字符串,避免JSON序列化报错
finally块增加非空判断,仅当user_json有有效值时才打印内容
内容的提问来源于stack exchange,提问作者Asif Azamuddin
相关产品推荐
相关产品推荐

