为什么在Tkinter按钮command中调用sqlite3的cursor.execute不生效?
问题原因
- 数据库写入操作未提交事务:sqlite3 默认对写入类操作(UPDATE/INSERT/DELETE)开启事务,必须调用
conn.commit()才能将修改真正写入数据库文件。你直接调用函数时如果后续程序立即退出,部分运行环境会自动提交未完成的事务,但绑定按钮触发时程序处于持续运行状态,未提交的修改不会持久化,也不会在后续查询中返回。 - 打印内容为初始化缓存的旧数据:
postsFetch是程序启动时一次性查询得到的静态结果,数据库更新后你没有重新执行查询逻辑,所以即使修改成功,print(postsFetch)输出的还是旧数据,会造成修改未生效的错觉。 - 按钮未正确渲染到界面:代码中创建按钮时指定的父容器
post没有定义,且没有调用pack()/grid()等布局方法,按钮根本不会显示在界面上,自然无法触发点击事件。 - 路径写法存在兼容性风险:Windows 路径中的反斜杠需要转义,否则可能被识别为转义字符导致找不到数据库文件。
- 存在SQL注入风险:使用f字符串拼接SQL语句容易引发注入问题,建议使用sqlite3内置的参数化查询写法。
修复后的参考代码
from tkinter import * import sqlite3 # 数据库路径用原始字符串避免转义问题 conn = sqlite3.connect(r"dbs\postit.db") cursor = conn.cursor() # 把查询逻辑封装成函数,方便更新后重新获取数据 def refresh_posts(): cursor.execute("SELECT rowid, * FROM postits") return cursor.fetchall() postsFetch = refresh_posts() print(f"初始数据:{postsFetch}") def createPost(): for postit in postsFetch: if postit[1] == "name": print("ok") def savePost(): # 用参数化查询代替f字符串拼接 cursor.execute("UPDATE postits SET content = ? WHERE name = ?", ("test02", "name")) # 提交事务,把修改写入数据库 conn.commit() # 重新查询数据获取最新结果 global postsFetch postsFetch = refresh_posts() print(f"更新后数据:{postsFetch}") # 初始化根窗口(补上缺失的父容器定义) root = Tk() # 按钮父容器指定为根窗口,调用pack渲染到界面 saveBtn = Button(root, text="Save", command=savePost) saveBtn.pack() # 启动Tkinter事件循环 root.mainloop() # 程序退出前关闭数据库连接 conn.close()
内容的提问来源于stack exchange,提问作者Fovu
相关产品推荐
相关产品推荐

