ZetCode

Python sqlite3.Blob.close Method

Last modified April 15, 2025

This comprehensive guide explores Python's sqlite3.Blob.close method, used for managing binary data in SQLite databases. We'll cover blob handling, resource management, and practical examples.

Basic Definitions

The sqlite3.Blob class represents binary large objects (BLOBs) in SQLite databases. It provides sequential access to binary data stored in tables.

The close method releases resources associated with the blob. It's essential for proper resource management when working with binary data in SQLite.

Basic Blob Handling

This example demonstrates basic blob creation and closing using the context manager pattern for automatic resource cleanup.

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()

This example creates a database table for storing images, inserts a sample image, then reads the first bytes from the blob. The blob is properly closed in a finally block.

The blobopen method creates a blob handle for accessing binary data. The parameters specify table, column, rowid, and database name.

Blob in Context Manager

SQLite blobs can be used with context managers for automatic closing, similar to file objects.

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

This example shows blob handling using Python's context manager protocol. The blob is automatically closed when exiting the with block.

The context manager pattern is recommended as it ensures proper resource cleanup even if exceptions occur during blob operations.

Blob Streaming

Blobs can be processed in chunks for memory-efficient handling of large binary data.

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()

This example demonstrates streaming processing of a large blob in chunks. The blob is read in 4KB chunks to avoid loading the entire content into memory.

The blob is automatically closed by the context manager after processing completes, ensuring no resource leaks occur.

Blob Writing

Blobs can be written to in addition to being read, allowing for in-place updates of binary data.

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()

This example shows how to open a blob in write mode and modify its content. The writeable=True parameter enables writing to the blob.

The blob is automatically closed after writing, and the transaction is committed when exiting the connection context manager.

Error Handling

Proper error handling is essential when working with blobs to ensure resources are cleaned up even when errors occur.

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()

This example demonstrates robust error handling when working with blobs. The finally block ensures both the blob and connection are properly closed.

While context managers are preferred, this pattern is useful when you need more control over error handling and resource cleanup.

Multiple Blobs

Applications often need to work with multiple blobs simultaneously, requiring careful resource management.

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()

This example processes multiple blobs in sequence, calculating SHA-256 hashes for each. Each blob is automatically closed after processing.

The pattern ensures no resource leaks occur even when processing many blobs, as each is properly managed within its own context.

Blob with Transactions

Blob operations participate in database transactions, requiring proper transaction management.

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()

This example demonstrates how blob operations participate in transactions. The simulated error triggers a rollback, preserving data consistency.

The blob is properly closed even when the transaction fails, thanks to the context manager handling the cleanup.

Best Practices

Source References

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.