跨类传递data变量时触发MySQL ProgrammingError参数类型异常
问题分析与解决
核心错误原因
错误提示的ProgrammingError源于两个关键问题:
HabitTracker中重新创建了空的LoginOrReg实例,其data属性为初始空字符串,导致SQL参数类型不符合要求;- SQL执行时,单个参数的传递格式错误,未遵循元组的语法规范。
分步修复
1. 修正LoginOrReg.py的实例传递逻辑
在log_user_in方法中,要传递当前LoginOrReg的实例给HabitTracker,而非空值或类本身:
# 原创建HabitTracker的代码 self.habit = HT.HabitTracker(main_window=' ', sorting_options= ' ', sort= ' ', login= ' ') # 修改为:传入当前LoginOrReg实例 self.habit = HT.HabitTracker(main_window=' ', sorting_options= ' ', sort= ' ', login=self) # 原调用main_menu的代码 self.habit.main_menu(LoginOrReg) # 修改为:传入当前实例 self.habit.main_menu(self)
同时修正login方法中提前获取输入框值的问题——应该在用户点击登录按钮时再获取输入内容:
# 移除login方法内的这两行(此时输入框还未输入内容) # self.login_username = self.login_username_entry.get() # self.login_password = self.login_password_entry.get() # 在log_user_in方法内获取输入值 def log_user_in(self): input_username = self.login_username_entry.get() input_password = self.login_password_entry.get() # 后续SQL语句统一使用input_username和input_password
2. 修正HabitTracker.py的实例使用逻辑
main_menu方法不要重新创建LoginOrReg实例,直接使用传入的有效实例,同时修正SQL参数格式:
# 移除main_menu内的这两行(重新创建的实例是空的) # import LoginOrReg as LR # self.login = LR.LoginOrReg(db=' ', cursor= ' ', login_username=' ', data= ' ') # 原SQL执行代码 self.cursor.execute('SELECT habit_name FROM habit WHERE user_id=%s GROUP BY habit_name', (self.login.data)) # 修改为:单个元素的元组必须加逗号,直接使用已获取的user_id更清晰 self.cursor.execute('SELECT habit_name FROM habit WHERE user_id=%s GROUP BY habit_name', (self.login.user_id,))
3. 其他优化点
- 移除
LoginOrReg的__init__中未使用的db、cursor参数,简化初始化逻辑; - 登录成功后关闭登录窗口,避免多个窗口叠加;
- 数据库连接建议使用
with上下文管理器,防止资源泄漏。
修复后关键代码片段
LoginOrReg.py的log_user_in方法
def log_user_in(self): input_username = self.login_username_entry.get() input_password = self.login_password_entry.get() self.habit = HT.HabitTracker(main_window=' ', sorting_options= ' ', sort= ' ', login=self) self.cursor.execute('SELECT COUNT(*) FROM users WHERE username=%s AND password=%s',(input_username, input_password)) row_count = self.cursor.fetchone()[0] if row_count == 1: self.cursor.execute('SELECT userID FROM users WHERE username=%s AND password=%s',(input_username, input_password)) self.data = self.cursor.fetchone() self.user_id = self.data[0] self.habit.main_menu(self) self.login_window.destroy() # 关闭登录窗口 else: customtkinter.CTkLabel(self.login_window, text = "User Not Found. Please Try Again.", font=('Helvetica', 10)).pack(pady=10)
HabitTracker.py的main_menu方法
def main_menu(self, login_instance): self.login = login_instance self.date = datetime.today() self.main_window = customtkinter.CTk() self.main_window.geometry('1080x720') self.sorting_options = ['Daily', 'Weekly', 'Monthly', 'Highest Streak',] customtkinter.CTkLabel(self.main_window, text=f'Welcome {self.login.login_username_entry.get()}', font=('Arial', 40)).pack(pady=5) self.sort = customtkinter.CTkComboBox(self.main_window, values= self.sorting_options) self.sort.set('Sort By') self.sort.pack(pady=10) customtkinter.CTkButton(self.main_window, text='Create New Habit', fg_color='green').pack(pady=20) self.cursor.execute('SELECT habit_name FROM habit WHERE user_id=%s GROUP BY habit_name', (self.login.user_id,)) self.habits = self.cursor.fetchall() for habit in self.habits: customtkinter.CTkButton(self.main_window, text=habit[0], command=lambda k=habit[0]: print(f"Edit habit: {k}")).pack(pady=10) self.main_window.mainloop()
内容的提问来源于stack exchange,提问作者Kael Scanes
相关产品推荐
相关产品推荐

