ZetCode

Python sqlite3.Connection.close 方法

上次修改时间:2025 年 4 月 15 日

本指南全面探讨了 Python 的 sqlite3.Connection.close 方法,该方法对于正确的数据库资源管理至关重要。

基本定义

sqlite3.Connection.close 方法用于关闭数据库连接。它会释放与连接关联的所有资源。任何未显式提交的挂起事务都将被回滚。

主要特征:它是不可逆的,释放文件锁,并且在完成连接后应始终调用。未能关闭连接可能会导致资源泄漏和文件锁定问题。

基本连接关闭

此示例演示了带有显式连接管理的 close 方法的基本用法。

basic_close.py
import sqlite3

# Create a connection
conn = sqlite3.connect('test.db')

try:
    cursor = conn.cursor()
    cursor.execute("CREATE TABLE IF NOT EXISTS data (id INTEGER, value TEXT)")
    cursor.execute("INSERT INTO data VALUES (1, 'Sample')")
    conn.commit()
finally:
    # Ensure connection is closed even if error occurs
    conn.close()
    print("Connection closed successfully")

该示例展示了使用 try/finally 的正确资源清理。连接在 finally 块中关闭,以确保无论发生什么错误,它都会发生。

此模式是可靠数据库应用程序的基础。它可以防止因连接未正确关闭而可能发生的资源泄漏。

使用 With 语句

连接对象支持上下文管理器协议,从而可以在退出 with 块时自动关闭。

with_statement.py
import sqlite3

# Using connection as context manager
with sqlite3.connect('test.db') as conn:
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM data")
    print(cursor.fetchall())
    
# Connection automatically closed here
print("Connection closed by context manager")

with 语句确保在块退出时正确关闭连接,即使发生异常也是如此。这是推荐的方法。

此模式简化了资源管理,并通过消除显式 close 调用和 try/finally 块,使代码更具可读性。

嵌套 With 语句

可以使用嵌套的 with 语句管理多个资源(连接和游标),以实现清晰的资源处理。

nested_with.py
import sqlite3
from contextlib import closing

with sqlite3.connect('test.db') as conn:
    with closing(conn.cursor()) as cursor:
        cursor.execute("UPDATE data SET value = 'Updated' WHERE id = 1")
        conn.commit()
    # Cursor closed here
# Connection closed here
print("Both cursor and connection closed automatically")

此示例将 contextlib.closing 用于游标,因为它本身不支持上下文管理器。两个资源都已正确关闭。

嵌套的 with 语句为资源生命周期管理提供了清晰的可视结构,并确保所有资源都已正确释放。

带错误处理的连接关闭

此示例演示了正确的错误处理,同时确保在所有情况下都关闭连接。

error_handling.py
import sqlite3

try:
    conn = sqlite3.connect('test.db')
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM non_existent_table")
except sqlite3.Error as e:
    print(f"Database error: {e}")
finally:
    if 'conn' in locals():
        conn.close()
        print("Connection closed in finally block")

该代码尝试一个将失败的查询,捕获异常,并确保在 finally 块中关闭连接。 locals() 检查可防止 NameError。

此模式对于健壮的应用程序至关重要。它可以防止连接泄漏,同时仍然允许正确的错误处理和报告。

连接池模式

对于需要频繁连接的应用程序,可以实现带有正确关闭的连接池。

connection_pool.py
import sqlite3
from contextlib import contextmanager

@contextmanager
def get_connection():
    conn = sqlite3.connect('test.db')
    try:
        yield conn
    finally:
        conn.close()
        print("Connection returned to pool (closed)")

# Usage
with get_connection() as conn:
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM data")
    print(cursor.fetchone())

此示例创建了一个使用上下文管理器的简单连接池。当 with 块退出时,连接会自动关闭。

虽然 SQLite 不需要真正的连接池,但此模式有助于在整个应用程序中一致地管理连接,并确保正确的清理。

检查连接状态

关闭连接后,尝试使用它将引发错误。此示例显示了如何检查连接状态。

check_state.py
import sqlite3

conn = sqlite3.connect(':memory:')
conn.close()

try:
    # Attempt to use closed connection
    conn.execute("CREATE TABLE test (id INTEGER)")
except sqlite3.ProgrammingError as e:
    print(f"Error: {e}")  # Error: Cannot operate on a closed database.

该示例演示了对已关闭的连接执行操作会引发 ProgrammingError。 这有助于尽早发现编程错误。

在长时间运行的应用程序中,或者在可能希望重复使用连接对象时,请始终验证连接状态。 无法重新打开已关闭的连接。

多线程应用程序中的连接关闭

此示例显示了在多线程应用程序中正确的连接处理,其中每个线程都获得自己的连接。

multithreaded.py
import sqlite3
import threading

def worker():
    with sqlite3.connect('test.db') as conn:
        cursor = conn.cursor()
        cursor.execute("INSERT INTO data VALUES (?, ?)", (threading.get_ident(), 'Thread'))
        conn.commit()
    print(f"Thread {threading.get_ident()} connection closed")

# Create and start threads
threads = [threading.Thread(target=worker) for _ in range(3)]
for t in threads:
    t.start()
for t in threads:
    t.join()

每个线程创建并关闭自己的连接。 with 语句确保即使线程意外终止也能正确清理。

在多线程应用程序中,永远不要在线程之间共享连接。 每个线程都应管理自己的连接生命周期。

最佳实践

资料来源

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。 我自 2007 年以来一直在撰写编程文章。 迄今为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程