Streamlit创建账户报SQLite跨线程ProgrammingError如何解决
问题根源
SQLite 默认限制连接、游标对象只能在创建它的线程中使用,你的数据库操作代码在模块导入阶段就全局初始化了数据库连接conn和游标c,而 Streamlit 每次用户交互触发页面重跑时,大概率会切换到新线程执行逻辑,此时调用数据库方法复用了旧线程的连接对象,就会触发该报错。
修复方案
第一步:修改数据库操作文件(manage_db_1.py)
不要全局创建连接和游标,两种修复方式可选:
- 优先推荐安全写法:每次执行数据库操作时单独创建连接,操作完成后关闭,适配所有场景
import sqlite3 def create_usertable(): conn = sqlite3.connect("usersdata.db") c = conn.cursor() c.execute('CREATE TABLE IF NOT EXISTS userstable(username TEXT, password TEXT)') conn.commit() conn.close() def add_userdata(username, password): conn = sqlite3.connect("usersdata.db") c = conn.cursor() c.execute('INSERT INTO userstable(username,password) VALUES (?,?)', (username,password)) conn.commit() conn.close() def login_user(username, password): conn = sqlite3.connect("usersdata.db") c = conn.cursor() c.execute('SELECT * FROM userstable WHERE username =? AND password =?',(username,password)) data = c.fetchall() conn.close() return data def view_all_users(): conn = sqlite3.connect("usersdata.db") c = conn.cursor() c.execute('SELECT * FROM userstable') data = c.fetchall() conn.close() return data
- 小型个人项目简化写法:关闭SQLite的线程检查,修改全局连接创建代码即可,原有函数逻辑不用改
import sqlite3 # 新增check_same_thread=False参数关闭线程检查 conn = sqlite3.connect("usersdata.db", check_same_thread=False) c = conn.cursor() # 原有函数保持不变
第二步:修复主代码中的额外错误
你登录逻辑里存在未定义变量的错误:Login分支下的create_usertable(username1,password1)是无效代码,username1和password1没有定义,且创建用户表不需要传参,直接删除这行即可。同时优化登录参数传递逻辑,调整后代码如下:
elif choice == "Login": username = st.text_input("Username") password = st.text_input("Password", type="password") if st.sidebar.checkbox("Login"): # 删掉原来的错误行create_usertable(username1,password1) hashed_pswd = generate_hashes(password) result = login_user(username, hashed_pswd) if result: st.success("Welcome {}".format(username)) # 后续原有逻辑保持不变
修改完成后重新运行项目即可解决报错。
内容的提问来源于stack exchange,提问作者Elijah
相关产品推荐
相关产品推荐

