如何确保在调试期间关闭sqlite数据库连接?

2 投票
3 回答
4224 浏览
提问于 2025-04-17 19:53

我正在写一些代码,用来连接一个sqlite数据库。在调试这个代码的过程中,我遇到了一些问题,导致数据库的连接一直开着,因为某些错误阻止了关闭连接的命令执行。由于数据库(db)和连接(c)是在一个函数内部定义的,我无法在命令行中找到并关闭这些对象。它们就像是孤儿连接一样,但无论如何,这些连接会阻止我在关闭并重新打开交互控制台之前对数据库进行其他操作。下面是我的代码示例:

def something()
    db=sqlite3.connect('mydatabase')
    c=db.cursor()

    somecode
    lots of different things happening in here
    this may have errors
    thus stopping execution

    db.commit()
    c.close()
    db.close()

我尝试过使用try/except语句,并把最终的关闭操作放在一个"finally"块中,但这样会阻止异常信息在调试时返回到交互输出,导致问题“默默地”发生(也许我没有正确使用这部分?)。有没有更好的方法来解决这个问题?

3 个回答

0

要清理资源,只需要使用 finally

db = sqlite.connect(...)
try:
    ...
    c = db.cursor()
    try:
        ...
    finally:
        c.close()
    ...
finally:
    db.close()
3

正如Piotr所指出的,使用with语句可以让代码运行得更高效,尽管这样并不会明确地关闭数据库连接,如果用户希望这样做的话。这个问题在一个类似的提问中也有讨论,大家可以在这里找到。

使用with语句的好处是,如果with语句中的代码块没有出错,它会自动执行con.commit()方法;如果遇到错误,它则会执行con.rollback()方法。

下面是来自http://docs.python.org/2/library/sqlite3.html的示例。

import sqlite3

con = sqlite3.connect(":memory:")
con.execute("create table person (id integer primary key, firstname varchar unique)")

with con:
    con.execute("insert into person(firstname) values (?)", ("Joe",))

# If Successful, con.commit() is called automatically afterwards
# else con.rollback() is called after the with block finishes with an exception, 
# the exception is still raised and must be caught

try:
    with con:
        con.execute("insert into person(firstname) values (?)", ("Joe",))
except sqlite3.IntegrityError:
    print "couldn't add Joe twice"

注意这里使用了con.execute()这个快捷方法,它是数据库连接对象的方法。这个方法会自动为你创建游标对象并返回结果,因此你需要写的代码会更少。

7

一般来说,使用 with 语句是个好主意:

with sqlite.connect(...) as db:
    with db.cursor() as c:
        ...

with 语句可以保证在结束时或者出现错误时,会自动调用对象的 close() 方法。即使在里面调用了 return 或 yield,也不会影响这个过程。

想了解更多,可以点击这里: http://docs.python.org/2/reference/compound_stmts.html#with

撰写回答