tre*_*der 56 python sqlite database-connection
我正在做这样的事......
conn = sqlite3.connect(db_filename)
with conn:
cur = conn.cursor()
cur.execute( ... )
Run Code Online (Sandbox Code Playgroud)
with自动提交更改.但是文档没有提到关闭连接.
实际上我可以conn在以后的陈述中使用(我已经测试过).因此,似乎上下文管理器没有关闭连接.
我是否必须手动关闭连接.如果我把它打开怎么办?
编辑
我的结论......
__exit__,上下文管理器ONLY通过执行来提交更改conn.commit()with conn并且with sqlite3.connect(db_filename) as conn是同一件事.所以使用其中任何一个仍将使连接保持活跃with 语句不会创建新范围,因此在with的套件内创建的所有变量都可以在其外部访问Rog*_*nns 33
回答如果不关闭SQLite数据库会发生什么的具体问题,答案很简单,适用于在任何编程语言中使用SQLite.当通过代码显式关闭连接或通过程序退出隐式关闭连接时,将回滚任何未完成的事务.(回滚实际上是由下一个打开数据库的程序完成的.)如果没有未完成的事务打开,则没有任何反应.
这意味着您不必过多担心在进程退出之前始终关闭数据库,并且您应该注意确保启动它们并在适当的位置提交的事务.
这里有一个有效的潜在关注点,但了解sqlite如何运作也很重要:
1. connection open
2. transaction started
3. statement executes
4. transaction done
5. connection closed
Run Code Online (Sandbox Code Playgroud)
在数据正确性方面,您只需要担心事务而不是打开句柄.sqlite只对事务(*)或语句执行中的数据库保持锁定.
但是在资源管理方面,例如,如果您计划删除sqlite文件或使用如此多的连接,您可能会用完文件描述符,那么您也会关心打开的事务外连接.
关闭连接有两种方式:要么.close()显式调用,之后仍然有句柄但不能使用它,要么让连接超出范围并进行垃圾收集.
如果你必须关闭连接,请明确地关闭它,根据Python的座右铭" 显式优于隐式".
如果您只是检查副作用的代码,那么让持有对连接的引用的最后一个变量超出范围是可以接受的,但请记住,异常会捕获堆栈,从而捕获该堆栈中的引用.如果你传递异常,连接生命周期可以任意延长.
告诫程序员,sqlite默认使用"延迟"事务,即事务仅在执行语句时启动.在上面的示例中,事务从3到4运行,而不是从2运行到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()
Run Code Online (Sandbox Code Playgroud)
在快乐和特殊情况下都是安全的
这是我使用的代码。在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)
Run Code Online (Sandbox Code Playgroud)