如果我不在Python SQLite中关闭数据库连接怎么办?

时间:2012-03-05 04:57:35

标签: python sqlite database-connection

我正在做这样的事......

conn = sqlite3.connect(db_filename)

with conn:
    cur = conn.cursor()
    cur.execute( ... )

with会自动提交更改。但是文档没有提到关闭连接。

实际上我可以在后面的语句中使用conn(我已经测试过)。因此,似乎上下文管理器没有关闭连接。

我是否必须手动关闭连接。如果我把它打开怎么办?

修改

我的结论......

  • 上下文管理器中的连接未关闭,我已经测试并确认了它。在__exit__后,上下文管理器仅通过执行conn.commit()
  • 提交更改
  • with connwith sqlite3.connect(db_filename) as conn 同一件事。所以使用其中任何一个仍将保持连接活着
  • with语句不会创建新范围,因此在with的套件内创建的所有变量都可以在其外部访问
  • 最后,您应该手动关闭连接

6 个答案:

答案 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)

这是我使用的代码。由于ConnectionCursorcontextlib.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

这样做,我确定连接已明确关闭。