ZetCode

Python sqlite3.Blob.close 方法

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

本综合指南探讨了 Python 的 sqlite3.Blob.close 方法,该方法用于管理 SQLite 数据库中的二进制数据。我们将涵盖 blob 处理、资源管理和实际示例。

基本定义

sqlite3.Blob 类表示 SQLite 数据库中的二进制大对象 (BLOB)。它提供对表中存储的二进制数据的顺序访问。

close 方法释放与 blob 关联的资源。 在 SQLite 中处理二进制数据时,这对于正确的资源管理至关重要。

基本 Blob 处理

此示例演示了使用上下文管理器模式进行基本 blob 创建和关闭,以实现自动资源清理。

basic_blob.py
import sqlite3

with sqlite3.connect('blobs.db') as conn:
    conn.execute("CREATE TABLE IF NOT EXISTS images (id INTEGER PRIMARY KEY, data BLOB)")
    
    # Insert sample binary data
    with open('sample.png', 'rb') as f:
        data = f.read()
    conn.execute("INSERT INTO images (data) VALUES (?)", (data,))
    
    # Open blob for reading
    blob = conn.blobopen('images', 'data', 1, 'main')
    try:
        print(f"Blob size: {blob.length()} bytes")
        first_bytes = blob.read(10)
        print(f"First 10 bytes: {first_bytes}")
    finally:
        blob.close()

此示例创建一个数据库表来存储图像,插入一个示例图像,然后从 blob 中读取前几个字节。 该 blob 在 finally 块中正确关闭。

blobopen 方法创建一个 blob 句柄,用于访问二进制数据。 参数指定表、列、rowid 和数据库名称。

上下文管理器中的 Blob

SQLite blob 可以与上下文管理器一起使用以进行自动关闭,类似于文件对象。

blob_context.py
import sqlite3

with sqlite3.connect('blobs.db') as conn:
    conn.execute("CREATE TABLE IF NOT EXISTS documents (id INTEGER PRIMARY KEY, content BLOB)")
    
    # Insert sample document
    with open('report.pdf', 'rb') as f:
        conn.execute("INSERT INTO documents (content) VALUES (?)", (f.read(),))
    
    # Read blob using context manager
    with conn.blobopen('documents', 'content', 1) as blob:
        header = blob.read(4)
        print(f"PDF header: {header}")
        # Blob automatically closed when exiting 'with' block

此示例显示了使用 Python 的上下文管理器协议进行 blob 处理。 当退出 with 块时,blob 会自动关闭。

建议使用上下文管理器模式,因为它即使在 blob 操作期间发生异常也能确保正确的资源清理。

Blob 流式传输

可以分块处理 Blob,以实现大型二进制数据的内存高效处理。

blob_streaming.py
import sqlite3

def process_large_blob():
    with sqlite3.connect('large_data.db') as conn:
        with conn.blobopen('archives', 'data', 1) as blob:
            chunk_size = 4096
            total_read = 0
            
            while True:
                chunk = blob.read(chunk_size)
                if not chunk:
                    break
                total_read += len(chunk)
                # Process chunk here
                
            print(f"Processed {total_read} bytes")

process_large_blob()

此示例演示了以块形式对大型 blob 进行流式处理。 以 4KB 的块读取 blob,以避免将整个内容加载到内存中。

在处理完成后,上下文管理器会自动关闭 blob,确保不会发生资源泄漏。

Blob 写入

除了读取 blob 之外,还可以写入 blob,从而可以就地更新二进制数据。

blob_writing.py
import sqlite3

def update_blob():
    with sqlite3.connect('updates.db') as conn:
        conn.execute("CREATE TABLE IF NOT EXISTS files (id INTEGER PRIMARY KEY, data BLOB)")
        
        # Insert initial data
        conn.execute("INSERT INTO files (data) VALUES (?)", (b'Initial content',))
        
        # Open blob for writing
        with conn.blobopen('files', 'data', 1, writeable=True) as blob:
            blob.write(b'Updated ')
            blob.seek(0, 2)  # Seek to end
            blob.write(b' content')
            
        # Verify update
        updated = conn.execute("SELECT data FROM files WHERE id = 1").fetchone()[0]
        print(f"Updated content: {updated}")

update_blob()

此示例演示了如何在写入模式下打开 blob 并修改其内容。 writeable=True 参数启用对 blob 的写入。

写入后,blob 会自动关闭,并且在退出连接上下文管理器时会提交事务。

错误处理

处理 blob 时,正确的错误处理至关重要,以确保即使发生错误也能清理资源。

blob_errors.py
import sqlite3

def safe_blob_operation():
    conn = None
    blob = None
    try:
        conn = sqlite3.connect('important.db')
        blob = conn.blobopen('backups', 'data', 1)
        
        if blob.length() > 1000000:
            raise ValueError("Blob too large for processing")
            
        data = blob.read()
        # Process data
        
    except Exception as e:
        print(f"Error processing blob: {e}")
    finally:
        if blob is not None:
            blob.close()
        if conn is not None:
            conn.close()

safe_blob_operation()

此示例演示了处理 blob 时的可靠错误处理。 finally 块确保 blob 和连接都已正确关闭。

虽然首选上下文管理器,但在需要更多地控制错误处理和资源清理时,此模式很有用。

多个 Blob

应用程序通常需要同时处理多个 blob,这需要仔细的资源管理。

multiple_blobs.py
import sqlite3
import hashlib

def process_multiple_blobs():
    with sqlite3.connect('multi_blob.db') as conn:
        conn.execute("""CREATE TABLE IF NOT EXISTS assets 
                       (id INTEGER PRIMARY KEY, name TEXT, data BLOB)""")
        
        # Insert sample assets
        samples = [b'Asset1 data', b'Asset2 data', b'Asset3 data']
        for i, data in enumerate(samples, 1):
            conn.execute("INSERT INTO assets (name, data) VALUES (?, ?)",
                       (f'asset_{i}', data))
        
        # Process all blobs
        for rowid in range(1, 4):
            with conn.blobopen('assets', 'data', rowid) as blob:
                hash_obj = hashlib.sha256(blob.read()).hexdigest()
                print(f"Asset {rowid} SHA256: {hash_obj}")

process_multiple_blobs()

此示例按顺序处理多个 blob,计算每个 blob 的 SHA-256 哈希值。 每个 blob 在处理后都会自动关闭。

该模式确保即使在处理许多 blob 时也不会发生资源泄漏,因为每个 blob 都在其自己的上下文中得到正确管理。

带有事务的 Blob

Blob 操作参与数据库事务,需要正确的事务管理。

blob_transactions.py
import sqlite3

def transactional_blob_update():
    with sqlite3.connect('transactions.db', isolation_level='IMMEDIATE') as conn:
        conn.execute("CREATE TABLE IF NOT EXISTS versions (id INTEGER PRIMARY KEY, data BLOB)")
        
        # Insert initial version
        conn.execute("INSERT INTO versions (data) VALUES (?)", (b'v1.0',))
        
        try:
            # Start transaction
            with conn.blobopen('versions', 'data', 1, writeable=True) as blob:
                blob.write(b'v2.0')
                # Simulate error after partial write
                raise RuntimeError("Simulated failure")
                
        except Exception as e:
            print(f"Transaction failed: {e}")
            conn.rollback()
        else:
            conn.commit()

        # Verify data wasn't corrupted
        current = conn.execute("SELECT data FROM versions WHERE id = 1").fetchone()[0]
        print(f"Current version: {current}")

transactional_blob_update()

此示例演示了 blob 操作如何参与事务。 模拟的错误会触发回滚,从而保持数据一致性。

即使事务失败,blob 也能正确关闭,这要归功于上下文管理器处理清理。

最佳实践

资料来源

作者

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

列出所有 Python 教程