[ 问题解决 ] sqlite3.ProgrammingError: SQLite objects created in a thread can ...
目录
为什么会出现这个问题?
解决方法一:每个请求新建自己的连接(推荐)
解决方法二:允许 SQLite 跨线程使用连接(不推荐)
小结
当你在 python 中使用 Flask 里面调用了数据库的操作的时候:
def main():db = conn("DATABASE.db")Show(db)def Show(db):app = Flask(__name__)@app.route('/')def demo():db.execute("Select * from ***")db.fetchall()
出现了如下 ERROR:
sqlite3.ProgrammingError: SQLite objects created in a thread can only be used in that same thread.
这句话的意思是:
-
你在 一个线程(比如 Flask 启动时的主线程)里创建了 SQLite 的连接或者 cursor(光标对象)。
-
但你在 另一个线程(比如处理 POST 请求时 Flask 内部新开的线程)去用这个连接或者 cursor。
-
SQLite 默认不允许跨线程使用同一个连接。
SQLite 连接是线程绑定的,不同线程必须用自己的连接。
为什么会出现这个问题?
因为 Flask 默认是多线程运行的,每一个请求(特别是 POST 请求)都可能在不同线程中处理。如果你在 Flask 启动时创建了一个数据库连接并保存成了全局变量,然后在请求里用它,就会出错。
解决方法一:每个请求新建自己的连接(推荐)
最常见的方法是:
-
每次请求都新建一个连接
-
用完就关闭连接
可以在 Flask 里这样做:
import sqlite3
from flask import Flask, gapp = Flask(__name__)DATABASE = 'your_database.db'def get_db():if 'db' not in g:g.db = sqlite3.connect(DATABASE)return g.db@app.teardown_appcontext
def close_db(exception):db = g.pop('db', None)if db is not None:db.close()@app.route('/your_route', methods=['POST'])
def your_post_handler():db = get_db()cursor = db.cursor()cursor.execute('YOUR SQL QUERY')result = cursor.fetchall()# process result...return 'Done'
解释一下:
-
g
是 Flask 提供的一个每个请求独立的小存储区,它跟线程绑定,安全。 -
get_db()
确保每个请求只打开一次数据库连接。 -
@app.teardown_appcontext
这个函数确保请求结束时自动关闭连接。
这样就不会有跨线程问题了。
解决方法二:允许 SQLite 跨线程使用连接(不推荐)
还有一种方法是:修改连接参数,允许 SQLite 跨线程用同一个连接:
conn = sqlite3.connect(DATABASE, check_same_thread=False)
check_same_thread=False
表示允许在不同线程里使用同一个连接对象。
但是!!!
-
这样做存在潜在的并发访问问题(比如两个线程同时读写,容易出错)。
-
SQLite 本身并不是高并发数据库,这样做虽然能避免报错,但隐藏了数据不一致或崩溃的风险。
-
一般只在自己清楚怎么管理线程安全时才敢这么用。
所以 不推荐新手用。
小结
方案 | 特点 | 适用场景 |
---|---|---|
每个请求新建连接 | 最安全,Flask推荐 | 正常开发 |
check_same_thread=False | 有并发风险,需自己管理线程安全 | 小项目、测试用,不推荐 |