如何解决Python开发简易银行USSD服务时的UnboundLocalError报错
错误根源
你触发UnboundLocalError: local variable 'AccountNo' referenced before assignment的核心原因是代码逻辑顺序完全颠倒,同时存在USSD交互逻辑错误、方法调用参数不匹配、语法错误三类问题。
具体错误点
- 直接触发报错的问题:你在
text == "1"的分支中,刚输出「请输入账号」的提示,立刻调用了user.select(),既没有传入必填的账号参数,也还没拿到用户输入的账号内容;同时你把接口要返回的USSD提示直接覆盖成了select的返回值,交互逻辑完全错误。 - User类select方法语法错误:
row = list(cursor.fetchall)中fetchall是方法,必须加括号调用,正确写法是cursor.fetchall()。 - USSD逻辑判断规则全错:USSD的交互中,用户每一步输入的内容会用
*拼接,比如用户先选1(已注册用户),再输入账号1234,此时text的值是1*1234,level=2,你原来写的text == "1"+user_response判断条件完全不成立,导致后续逻辑走不通。 - 方法参数不匹配:
- User类定义的insert方法只接收6个参数,你注册分支中传了8个参数,调用会报错。
- Bank类的deposit、withdraw方法要求传入Balance参数,你调用时没有传参。
- 没有全局存储当前登录用户的信息:Bank类的view_balance、show_details方法依赖的用户属性完全没有赋值,调用会报错。
修复方案
第一步:修复User类的select方法
def select(self,accountno): dbcon = self.connection() select_sql = "select AccountNo,Nameofclient,Age,Gender,Phonenumber,Email,Balance FROM bankuserst WHERE AccountNo=%s" cursor = dbcon.cursor() try: cursor.execute(select_sql, accountno) row = cursor.fetchone() # 单账号查询用fetchone更合理,不需要fetchall dbcon.close() return row except Exception as e: print("exception", e) dbcon.close() return None
第二步:修复enterdetails函数的USSD交互逻辑
增加全局变量存储当前登录的用户信息,修正判断条件:
# 全局变量存储当前登录用户信息 current_user = None @app.route('/', methods=("POST", "GET")) def enterdetails(): global current_user session_id = request.values.get("sessionId", None) service_code = request.values.get("sessionCode", None) phone_number = request.values.get("phonenumber", None) text = request.values.get("text", "") text_array = text.split("*") level = len(text_array) response = "" if text == "": response = "CON WELCOME To 99's Mobile Banking Service\nAre you a:\n" response += "1.Registered Member\n" response += "2.New member\n" elif level == 1 and text == "1": # 第一步选已注册,提示输入账号 response = "CON WELCOME BACK\nENTER Account Number:\n" elif level == 2 and text_array[0] == "1": # 拿到用户输入的账号,查询用户 account_no = text_array[1] user_info = user.select(account_no) if not user_info: response = "END 账号不存在,请重新进入" else: current_user = user_info response = "CON To:\n" response += "1.Check Account Balance\n" response += "2.Deposit money\n" response += "3.Withdraw Cash\n" response += "4.Print Account MiniStatement\n" elif level ==3 and text_array[0] == "1" and text_array[2] == "1": # 查询余额 if not current_user: response = "END 请先登录" else: response = f"END Your Balance is KSH: {current_user[6]}" # 后面的存款、取款、注册逻辑可以参照上面的规则依次修正 else: response = "END Invalid Input" return response
其他补充修改建议
- 移除insert方法调用时多余的参数,和定义保持一致。
- 不要在交互分支中直接调用deposit、withdraw方法修改余额,等用户输入完金额后再执行修改操作。
- 注册流程的逻辑也要参照USSD的层级判断规则重新写,每一步对应一个level,依次收集用户的姓名、年龄等信息,最后再执行insert操作。
内容的提问来源于stack exchange,提问作者reappaa99
相关产品推荐
相关产品推荐

