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

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.当通过代码显式关闭连接或通过程序退出隐式关闭连接时,将回滚任何未完成的事务.(回滚实际上是由下一个打开数据库的程序完成的.)如果没有未完成的事务打开,则没有任何反应.

这意味着您不必过多担心在进程退出之前始终关闭数据库,并且您应该注意确保启动它们并在适当的位置提交的事务.

  • 长时间运行的进程(如Web应用程序)在退出时没有隐式关闭,因为没有退出. (4认同)

Dim*_*nek 9

这里有一个有效的潜在关注点,但了解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.

  • 我想当使用内存数据库时资源管理部分不适用(`sqlite3.connect(':memory:')`)?我希望在这种情况下不会使用文件描述符。 (2认同)

Jur*_*tić 9

您可以使用这样的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)
  • 连接
  • 开始交易
  • 创建一个数据库游标
  • 执行操作并返回结果
  • 关闭游标
  • 提交/回滚事务
  • 关闭连接

在快乐和特殊情况下都是安全的

  • 这很棒。请注意,如果您正在执行**不返回任何内容** 的内容,例如插入或更新,**cur.fetchall()** 将只返回一个空列表。 (2认同)

sta*_*010 6

这是我使用的代码。在ConnectionCursor会自动关闭感谢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)

  • 最里面的“with”有什么意义?释放一些内存?如果不使用上下文管理器,会遇到什么样的问题?如果不返回“cursor”,从函数返回不是等价的吗? (4认同)
  • @howdoicode 我没有看到任何来源可以证明您关于良好实践的主张。我对这个想法持开放态度,但也持怀疑态度。自从OP提出这个问题以来,十年很快就过去了,我们仍然没有关于该主题的良好实践是什么的可靠消息来源,也没有深入的解释**为什么**。我对引用 Python 的禅宗关于显式性持保留态度,因为在 Python 中显式释放动态数据或将对象标记为不可用并不是惯用的。这就是 GC 和 `__del__` 的用途。迪马的最后第二段令人不安,因为它暗示了语言的缺陷。 (2认同)