Python中sqlite3使用with语句后连接未自动关闭?原因解析
SQLite with块结束后游标仍能执行查询的原因
问题代码
import sqlite3 with sqlite3.connect("test.db") as db: cursor = db.cursor() cursor.execute("""CREATE TABLE IF NOT EXISTS testtable(id integer PRIMARY KEY, name text);""") cursor.execute("""INSERT INTO testtable(id, name) VALUES (1, "XYZ")""") db.commit() cursor.execute("select * from testtable") for x in cursor.fetchall(): print(x)
问题说明
按with语句的常规逻辑,数据库连接应该在代码块结束时自动关闭,不用手动调用db.close(),就像处理文件那样。照理说with块外的cursor.execute()会因为连接失效报错,但实际这段代码却能正常运行并查到数据,这是怎么回事?
原因解析
- SQLite的Connection对象对with的实现和文件不一样:with块结束时,它不会直接关闭连接,只会自动执行回滚(如果没手动调用
db.commit()的话),连接本身依然处于活跃状态。只有当这个Connection对象被Python的垃圾回收机制回收时,才会真正关闭底层的数据库连接。 - 你在with块内创建的游标cursor,关联的是
db这个连接对象,只要db还在内存中没被回收,cursor就能继续借助这个连接执行查询操作。 - 可以自行验证:在with块后添加
print(db.closed),会输出False,说明连接确实未关闭;如果手动执行del db销毁连接对象,再用cursor执行查询就会直接报错。
注意事项
虽然这段代码能运行,但绝对不推荐这么写:
- 不符合资源管理的最佳实践,容易造成连接泄漏,尤其是在循环或长期运行的程序中。
- 一旦Connection对象被垃圾回收,后续的游标操作会直接报错,引发不可预期的问题。
内容的提问来源于stack exchange,提问作者styx
相关产品推荐
相关产品推荐

