Python SQLite:IndexError:列表索引超出范围

时间:2018-10-29 11:18:05

标签: python sql sqlite

conn = database_connect()
if(conn is None):
    return None
cur = conn.cursor()
try:
    # Try executing the SQL and get from the database
    sql = """SELECT *
            FROM user
            WHERE user_id**strong text** =%s AND password =%s"""
    cur.execute(sql, (employee_id, password))
    r = cur.fetchone()# Fetch the first row
    rr = cur.fetchall()
    cur.close()                     # Close the cursor
    conn.close()                    # Close the connection to the db

except:
# If there were any errors, return a NULL row printing an error to the debug
    print("Error Invalid Login")
    cur.close()                     # Close the cursor
    conn.close()                    # Close the connection to the db
    return None

user_info = []
if rr is None:
    print("worry")
    return []

for n in rr:
    user_info.append(n)

test = {
    'info1': user_info[0],
    'info2': user_info[1],
    'info3': user_info[2],
    'info4': user_info[3],
}

return test

这是我的代码。首先实现登录功能,然后获取用户信息,但是有一个IndexError: list index out of range。我该如何解决?

1 个答案:

答案 0 :(得分:0)

这里:

r = cur.fetchone()# Fetch the first row
rr = cur.fetchall()

fetchone()的调用将占用第一行,因此rr将包含n-1行。

此外,如果您的数据库允许重复的user_id,那么您将遇到一个严重的数据库设计问题-user_id是(应该是)主键还是“用户名”(登录名),它实际上应该是唯一的。如果不是,那么您想更改模式,如果它确实是唯一的,那么显然您的查询只能返回(最多!)一行,在这种情况下,rr被保证始终为空(因为您通过fetchone()调用消耗了第一行。

请注意,这是一些可能的改进:

此:

for n in rr:
    user_info.append(n)

完全没用-您只是在构建rr的浅表副本,而是直接与rr一起使用。

那么不要假设查询结果中总是有四行,因此至少要动态构建test字典:

test = {}
# enumerate(seq) yields an index, value tuple
# for each value in `seq`.
for num, row in enumerate(rr, 1):
    key = "info{}.format(num)
    test[key] = row

或更简洁:

test = {"info{}".format(num):row for num, row in enumerate(rr, 1)}

请注意,与rr相比,此dict不会增加太多价值-您具有“信息”键而不是数字索引,仅此而已,因此您可以直接使用rr列表

最后但并非最不重要的一点是,您的try / except子句太宽泛(try块中的代码太多),except子句会吃掉非常有价值的调试信息(确切的错误消息和完整的追溯),甚至更糟的是,您显示的错误消息对实际情况的假设过多。实际上,您甚至可能在这里甚至都没有except子句(至少直到您真正知道这里可能发生什么错误并在此时正确处理为止),这样才能更好地传播错误(这样您就可以获得完整的错误消息和回溯信息) ),然后使用finally子句关闭您的连接:

sql = """SELECT *
        FROM user
        WHERE user_id**strong text** =%s AND password =%s"""

try:
    cur.execute(sql, (employee_id, password))
    r = cur.fetchone()# Fetch the first row
    rr = cur.fetchall()
finally:
    # this will always be executed whatever happens in the try block
    cur.close()                     # Close the cursor
    conn.close()                    # Close the connection to the db