Files
Auto-Finance/.agents/docs/error-experience/2026-06-13-闭包内复用外层变量名导致UnboundLocalError.md

2.4 KiB
Raw Permalink Blame History

last_reviewed
last_reviewed
2026-06-13

闭包内复用外层变量名导致 UnboundLocalError

错误现象

  • 补充材料提交后,提取函数正常执行完成
  • 日志停在 travel_applications.json 保存处,后续没有任何 Agent 处理日志
  • 没有报错、没有异常堆栈,看起来像"停止"
  • result.json 里实际记录了 {"ok": false, "error": "local variable 'agent_session' referenced before assignment"}

触发条件

  • 在 Flask 路由中用 threading.Thread 启动后台任务
  • 外层作用域已有一个变量(如 agent_session
  • 闭包 _run() 内对同名变量既读又写:agent_session = run_agent_round(session_dir, agent_session, ...)

原因

Python 变量作用域规则:只要函数体内有任何对某标识符的赋值,该标识符在整个函数内都被视为局部变量

agent_session = add_supplement(session_dir, agent_session, filenames)  # 外层变量

def _run() -> None:
    # ...
    agent_session = run_agent_round(       # 赋值 -> 整个 _run 内 agent_session 是局部变量
        session_dir, agent_session,        # 读局部变量,但此时还未赋值 -> UnboundLocalError
        new_files=filenames,
    )

run_agent_round 调用时,agent_session 作为参数被求值,但此时它还是未初始化的局部变量,触发 UnboundLocalError。该异常被 except BaseException 捕获后写入 result.json没有在日志中输出所以表现为"静默停止"。

修复方法

闭包内使用不同名称接收返回值:

# 修复前
agent_session = run_agent_round(session_dir, agent_session, new_files=filenames)

# 修复后
new_session = run_agent_round(session_dir, agent_session, new_files=filenames)

后续对返回值的引用统一改为 new_session

防回归要点

场景 风险 检查方法
在闭包/嵌套函数内赋值与外层同名的变量 UnboundLocalError ruff F823 规则
except BaseException 吞掉异常且不打日志 静默失败,难以排查 至少记录 log.exception
# noqa: F823 压制警告而不修复 问题持续存在 noqa 只应用于确认安全的场景

核心原则:在闭包内需要接收外层变量的返回值时,始终使用不同的变量名。不要依赖 nonlocal 来修复合法性问题——换名字更简单、更安全。