我正在做这样的事......
conn = sqlite3.connect(db_filename)
with conn:
cur = conn.cursor()
cur.execute( ... )
with
会自动提交更改。但是文档没有提到关闭连接。
实际上我可以在后面的语句中使用conn
(我已经测试过)。因此,似乎上下文管理器没有关闭连接。
我是否必须手动关闭连接。如果我把它打开怎么办?
修改
我的结论......
__exit__
后,上下文管理器仅通过执行conn.commit()
with conn
和with sqlite3.connect(db_filename) as conn
同一件事。所以使用其中任何一个仍将保持连接活着with
语句不会创建新范围,因此在with的套件内创建的所有变量都可以在其外部访问答案 0 :(得分:32)
在回答如果不关闭SQLite数据库会发生什么的具体问题时,答案非常简单,适用于在任何编程语言中使用SQLite。当通过代码显式关闭连接或通过程序退出隐式关闭连接时,将回滚任何未完成的事务。 (回滚实际上是由下一个打开数据库的程序完成的。)如果没有未完成的事务打开,则没有任何反应。
这意味着您不必过多担心在进程退出之前总是关闭数据库,并且您应该注意确保启动它们并在适当的位置提交的事务。
答案 1 :(得分:8)
这里有一个有效的潜在问题,但了解sqlite如何运作也很重要:
1. connection open
2. transaction started
3. statement executes
4. transaction done
5. connection closed
就数据正确性而言,您只需要担心交易而不是打开句柄。 sqlite只对事务(*)或语句执行中的数据库保持锁定。
然而,就资源管理而言,例如如果您打算删除sqlite文件或使用如此多的连接,您可能会用完文件描述符,那么您也会关心打开的事务外连接。
关闭连接有两种方式:要么显式调用.close()
,之后仍然有句柄但不能使用它,要么让连接超出范围并进行垃圾收集。
如果必须关闭连接,请明确关闭它,根据Python的座右铭“显式优于隐式。”
如果您只是检查副作用的代码,那么让持有对连接的引用的最后一个变量超出范围是可以接受的,但请记住,异常会捕获堆栈,从而捕获该堆栈中的引用。如果你传递异常,连接生命周期可以任意延长。
警告程序员,sqlite默认使用“延迟”事务,即事务仅在执行语句时启动。在上面的示例中,事务从3到4运行,而不是从2到4。
答案 2 :(得分:5)
这是我使用的代码。由于Connection
,Cursor
和contextlib.closing()
会自动关闭。由于上下文管理器,Connection
将自动提交。
import sqlite3
import contextlib
def execute_statement(statement):
with contextlib.closing(sqlite3.connect(path_to_file)) as conn: # auto-closes
with conn: # auto-commits
with contextlib.closing(conn.cursor()) as cursor: # auto-closes
cursor.execute(statement)
答案 3 :(得分:4)
您可以像这样使用with
块:
from contextlib import closing
import sqlite3
def query(self, db_name, sql):
with closing(sqlite3.connect(db_name)) as con, con, \
closing(con.cursor()) as cur:
cur.execute(sql)
return cur.fetchall()
在快乐和特殊情况下都是安全的
答案 4 :(得分:1)
您的版本在连接使用后将conn留在范围内。
实施例
您的版本
conn = sqlite3.connect(db_filename) #DECLARE CONNECTION OUT OF WITH BLOCK
with conn: #USE CONNECTION IN WITH BLOCK
cur = conn.cursor()
cur.execute( ... )
#conn variable is still in scope, so you can use it again
新版
with sqlite3.connect(db_filename) as conn: #DECLARE CONNECTION AT START OF WITH BLOCK
cur = conn.cursor()
cur.execute( ... )
#conn variable is out of scope, so connection is closed
# MIGHT BE IT IS NOT CLOSED BUT WHAT Avaris SAID!
#(I believe auto close goes for with block)
答案 5 :(得分:0)
为了管理与数据库的连接,我通常会这样做,
# query method belonging to a DB manager class
def query (self, sql):
con = sqlite3.connect(self.dbName)
with con:
cur = con.cursor()
cur.execute(sql)
res = cur.fetchall()
if con:
con.close()
return res
这样做,我确定连接已明确关闭。