You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 17:48:12