Python Tkinter命令处理触发IndexError列表索引越界报错排查
报错原因
- 直接触发越界的是
BALANCE分支的if words[1] == ''语句:当你输入的命令只有BALANCE没有后续参数时,text.split()生成的words列表长度只有1,不存在下标为1的元素,直接访问就会抛出IndexError。 - 你此处的判断逻辑本身也有错误:
split()方法默认会合并连续空白、忽略首尾空白,切割后的列表元素不可能出现空字符串,因此words[1] == ''这个条件永远无法命中,你原本想实现的“输入BALANCE不带参数就查询所有用户余额”的需求本来就无法运行。 - 另外你的
BALANCE分支else逻辑里还有缩进错误:conn.close()写在了for循环内部,第一次遍历到符合条件的行后就会关闭数据库连接,后续遍历会直接报错。同时DEPOSIT、WITHDRAW分支没有主动关闭数据库连接,存在连接泄漏问题。
修复方案
核心修改点
- 访问列表下标前先校验列表长度,避免越界;
- 将
BALANCE的参数判断改为判断列表长度:长度为1说明不带参数,查询所有用户余额;长度为2说明带用户名参数,查询对应用户的余额; - 修正
conn.close()的缩进,放到for循环外部,同时给所有操作数据库的分支补充关闭连接的逻辑; - 给所有命令都加上参数长度校验,避免其他命令输入参数不足时也触发同类报错。
修改后的Test函数代码
def Test(): text = str(Entry1.get()) words = text.split() # 先判空,避免空输入时访问words[0]也越界 if not words: return if words[0] == 'DEPOSIT': # 校验DEPOSIT需要3个参数:命令+用户名+金额 if len(words) < 3: return conn = sqlite3.connect('database.db') cur = conn.cursor() info = cur.execute('SELECT * FROM data WHERE name=?', (words[1],)) if info.fetchone() is None: cur.execute("INSERT INTO data VALUES (?, ?);", (words[2], words[1])) conn.commit() v.set(words[1]) b.set(words[2]) else: cur.execute("SELECT id FROM data WHERE name = ?", (words[1],)) result = cur.fetchone() cur.execute("UPDATE data SET id = ? WHERE name = ?", (int(result[0]) + int(words[2]), words[1])) conn.commit() cur.execute("SELECT id FROM data WHERE name = ?", (words[1],)) result = cur.fetchone() v.set(words[1]) b.set(result) # 补充关闭数据库连接 conn.close() elif words[0] == 'WITHDRAW': # 校验WITHDRAW需要3个参数:命令+用户名+金额 if len(words) < 3: return conn = sqlite3.connect('database.db') cur = conn.cursor() info = cur.execute('SELECT * FROM data WHERE name=?', (words[1],)) if info.fetchone() is None: cur.execute("INSERT INTO data VALUES (?, ?);", (int(words[2]) * -1, words[1])) conn.commit() v.set(words[1]) b.set(words[2]) else: cur.execute("SELECT id FROM data WHERE name = ?", (words[1],)) result = cur.fetchone() cur.execute("UPDATE data SET id = ? WHERE name = ?", (int(result[0]) - int(words[2]), words[1])) conn.commit() cur.execute("SELECT id FROM data WHERE name = ?", (words[1],)) result = cur.fetchone() v.set(words[1]) b.set(result) # 补充关闭数据库连接 conn.close() elif words[0] == 'CLEAR': tree.delete(*tree.get_children()) elif words[0] == 'BALANCE': # 长度为1:查询所有用户余额 if len(words) == 1: conn = sqlite3.connect("database.db") cur = conn.cursor() cur.execute("SELECT * FROM data") rows = cur.fetchall() for row in rows: tree.insert("", tk.END, text=row[0], values=row[1:]) conn.close() # 长度为2:查询指定用户余额 elif len(words) == 2: conn = sqlite3.connect("database.db") cur = conn.cursor() cur.execute("SELECT * FROM data") rows = cur.fetchall() for row in rows: if words[1] == row[1]: tree.insert("", tk.END, text=row[0], values=row[1:]) # 修正缩进,放到循环外部 conn.close()
内容的提问来源于stack exchange,提问作者DuckSide
相关产品推荐
相关产品推荐

