Python从MySQL取密码返回None的原因分析及解决方法
问题原因分析及解决办法
我来帮你拆解下代码里的问题,这两个关键点导致你拿到的DbPassword是None,还会引发后续的密码比对失败:
1. 参数传递错误,导致查询匹配不到任何用户
你执行SQL的代码是这样的:
cur.execute(sql,(User))
这里的坑在于:单个元素的元组必须在末尾加逗号,不然(User)只是把变量加了个括号,不是元组。MySQL连接器会把字符串User当成序列来遍历,把每个字符拆成单独的参数传给SQL,最终执行的SQL会变成类似:
SELECT password FROM users WHERE user_name = 'H' 'e' 'm' 'a' 'n' 't'
这种条件根本找不到对应的用户,所以cur.fetchone()自然返回None。
2. 密码比对的逻辑错误
就算运气好查到了结果,fetchone()返回的是一个元组(比如密码是qwerty的话,返回('qwerty',)),你直接转成字符串会得到"('qwerty',)",和用户输入的纯密码字符串肯定不相等,这也会导致登录验证失败。
修复后的完整代码
下面是修正后的searchdb函数,我还加了一些边界情况的处理:
def searchdb(self): User = self.Username.get() pas = self.Password.get() myconn = mysql.connector.connect(host="localhost", user="root", passwd="qwerty321", database="admin") if len(User) == 0 and len(pas) == 0 : tkinter.messagebox.showinfo("Pharmacy Management System","Please fill in the Login Details") elif len(User) == 0 and len(pas) != 0 : tkinter.messagebox.showinfo("Pharmacy Management System","Please Enter a Username") elif len(User) != 0 and len(pas) == 0: tkinter.messagebox.showinfo("Pharmacy Management System","Please enter a Password") else: try: # 注意:这里的%s不需要加引号,连接器会自动处理 sql = "SELECT password FROM users WHERE user_name = %s" cur = myconn.cursor() # 单元素元组必须加逗号,确保参数正确传递 cur.execute(sql, (User,)) DbPassword = cur.fetchone() # 先判断是否查到用户 if DbPassword is not None: # 取出元组里的第一个元素,也就是数据库中存储的密码 db_stored_pwd = DbPassword[0] print(db_stored_pwd) if pas == db_stored_pwd : self.btnRegistration.config(state=NORMAL) self.btnHospital.config(state=NORMAL) else: tkinter.messagebox.askokcancel("Pharmacy Management System","You have entered an invalid login details") self.btnRegistration.config(state=DISABLED) self.btnHospital.config(state=DISABLED) self.Username.set("") self.Password.set("") self.txtUsername.focus() else: # 没有查到对应用户的情况 tkinter.messagebox.askokcancel("Pharmacy Management System","No user found with this username") self.Username.set("") self.Password.set("") self.txtUsername.focus() except Error as e: print(f"数据库错误信息: {e}") myconn.rollback() Window1.Reset(self) finally: # 无论成功还是失败,都要关闭数据库连接,避免资源浪费 myconn.close()
额外的几个小建议
- 绝对不要用字符串拼接的方式写SQL(比如你原来的
sql = "SELECT password FROM users WHERE user_name = '%s'"),这会有SQL注入的风险,用参数化查询才是安全的做法。 - 数据库连接一定要记得关闭,用
finally块能保证无论代码是否报错,连接都会被关闭。 - 处理查询结果时,先判断
fetchone()是否为None,不然直接取元素会抛出TypeError异常。
内容的提问来源于stack exchange,提问作者Hemant kumar Pandit
相关产品推荐
相关产品推荐

