执行查询后关闭连接仍触发sqlite3.ProgrammingError:无法操作已关闭数据库
问题原因
你遇到的错误是因为第二个查询仅创建了游标对象但未立即获取数据:
posts调用了fetchall(),会立即执行查询并把结果加载到内存中,不依赖后续的连接状态users只是保存了connection.execute()返回的游标,这个游标需要保持数据库连接才能读取数据,而你在创建游标后立刻关闭了连接,后续访问users时就会触发错误
修复方案
有两种简单的修复方式:
方式一:提前获取users的数据
在关闭连接前,给第二个查询也加上fetchall(),把结果加载到内存:
import sqlite3 def database(): connection = sqlite3.connect('database.db') connection.row_factory = sqlite3.Row return connection def _index(): connection = database() posts = connection.execute('SELECT P.title, P.content, P.created, U.username FROM posts P JOIN users U ON P.author_id = U.id').fetchall() # 加上fetchall(),提前获取所有数据 users = connection.execute('SELECT U.fullname as "username", C.fullname as "committeename" FROM users U JOIN committees C ON U.committee_id = C.id').fetchall() connection.close() # 现在可以正常使用posts和users了
方式二:使用上下文管理器自动管理连接
用with语句包裹连接操作,它会在代码块结束后自动关闭连接,确保所有查询操作都在连接打开时完成:
import sqlite3 def database(): connection = sqlite3.connect('database.db') connection.row_factory = sqlite3.Row return connection def _index(): with database() as connection: posts = connection.execute('SELECT P.title, P.content, P.created, U.username FROM posts P JOIN users U ON P.author_id = U.id').fetchall() users = connection.execute('SELECT U.fullname as "username", C.fullname as "committeename" FROM users U JOIN committees C ON U.committee_id = C.id').fetchall() # with块结束后自动关闭连接,此时posts和users已经是内存中的数据,可正常使用
内容的提问来源于stack exchange,提问作者San
相关产品推荐
相关产品推荐

