Python sqlite3.Blob.read 方法
上次修改时间:2025 年 4 月 15 日
本综合指南探讨了 Python 的 sqlite3.Blob.read
方法,该方法用于从 SQLite BLOB 列中读取二进制数据。我们将介绍基本用法、参数和实际示例,并进行适当的资源管理。
基本定义
sqlite3.Blob
类表示 SQLite 数据库中的二进制大对象 (BLOB)。它提供了有效读取和写入二进制数据的方法。
read
方法从 BLOB 列中检索二进制数据。它接受参数来控制读取多少数据以及从何处开始读取。
基本 BLOB 读取
本示例演示了如何使用 read
方法,通过适当的资源管理,从数据库中读取整个 BLOB。
import sqlite3 # Create a database with BLOB data 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: conn.execute("INSERT INTO images (data) VALUES (?)", (f.read(),)) # Read the BLOB with conn.blobopen('images', 'data', 1, 'main') as blob: image_data = blob.read() print(f"Read {len(image_data)} bytes from BLOB") print("Database connection automatically closed")
本示例创建一个包含 BLOB 列的数据库,从文件中插入二进制数据,然后使用 blob.read
将其读回。 with
语句确保适当的资源清理。
blobopen
方法为指定的表、列和行创建一个 Blob 对象。当不带参数调用时,read
方法读取所有数据。
读取部分 BLOB 数据
read
方法可以通过指定大小和偏移量参数来读取 BLOB 的特定部分。
import sqlite3 with sqlite3.connect('partial.db') as conn: conn.execute("CREATE TABLE IF NOT EXISTS documents (id INTEGER, content BLOB)") # Insert large binary data large_data = b'X' * 1024 * 1024 # 1MB of data conn.execute("INSERT INTO documents VALUES (1, ?)", (large_data,)) # Read first 100 bytes with conn.blobopen('documents', 'content', 1, 'main') as blob: first_chunk = blob.read(100) print(f"First 100 bytes: {len(first_chunk)}") # Read next 200 bytes from offset 100 next_chunk = blob.read(200, 100) print(f"Next 200 bytes: {len(next_chunk)}") print("Resources automatically released")
本示例演示了读取大型 BLOB 的特定部分。第一个 read
获取前 100 个字节,而第二个从偏移量 100 开始读取 200 个字节。
部分读取对于处理大型 BLOB 非常有用,而无需一次将所有内容加载到内存中,从而提高内存效率。
分块读取 BLOB
对于非常大的 BLOB,您可以使用带有 read
方法的循环分块读取数据。
import sqlite3 CHUNK_SIZE = 4096 # 4KB chunks with sqlite3.connect('large_blobs.db') as conn: conn.execute("CREATE TABLE IF NOT EXISTS videos (id INTEGER, frames BLOB)") # Insert sample video data (simulated) video_data = b'FRAME' * 100000 # ~500KB conn.execute("INSERT INTO videos VALUES (1, ?)", (video_data,)) # Process in chunks with conn.blobopen('videos', 'frames', 1, 'main') as blob: total_read = 0 while True: chunk = blob.read(CHUNK_SIZE, total_read) if not chunk: break total_read += len(chunk) print(f"Processed chunk {len(chunk)} bytes, total {total_read}") print(f"Finished processing {total_read} bytes")
本示例以 4KB 的块读取一个大的 BLOB,分别处理每个块。循环持续到 read
返回一个空字节对象为止。
分块读取对于处理非常大的二进制对象,同时保持应用程序中合理的内存使用至关重要。
使用不同偏移量读取 BLOB
read
方法的 offset 参数允许从 BLOB 中的任何位置读取,从而可以随机访问二进制数据。
import sqlite3 with sqlite3.connect('offset.db') as conn: conn.execute("CREATE TABLE IF NOT EXISTS binary (id INTEGER, data BLOB)") # Insert patterned data data = bytes(range(256)) # 0-255 byte values conn.execute("INSERT INTO binary VALUES (1, ?)", (data,)) # Read from various offsets with conn.blobopen('binary', 'data', 1, 'main') as blob: # Read first 10 bytes print("Start:", blob.read(10)) # Read 10 bytes from middle print("Middle:", blob.read(10, 128)) # Read last 10 bytes print("End:", blob.read(10, 246)) print("All reads completed")
本示例插入一个包含字节 0-255 的 BLOB,然后演示从不同位置读取。 每个 read
操作都指定大小和偏移量。
随机访问对于具有已知结构的格式特别有用,在这种情况下,您需要读取二进制数据的特定部分而无需处理所有内容。
处理空 BLOB
read
方法对空 BLOB 的行为不同,返回一个空字节对象。 本示例演示了正确的处理方法。
import sqlite3 with sqlite3.connect('empty.db') as conn: conn.execute("CREATE TABLE IF NOT EXISTS files (name TEXT, content BLOB)") # Insert empty BLOB conn.execute("INSERT INTO files VALUES ('empty.txt', ?)", (b'',)) # Attempt to read with conn.blobopen('files', 'content', 1, 'main') as blob: data = blob.read() if not data: print("BLOB is empty") else: print(f"Read {len(data)} bytes") print("Database connection closed")
本示例插入一个空 BLOB(零长度字节),并演示如何检查此情况。 对于空 BLOB,read
方法返回 b''
。
处理可能为空的 BLOB 时,始终检查 read
的返回值,以避免将空数据作为有效内容处理。
BLOB 读取的错误处理
本示例演示了读取 BLOB 时的正确错误处理,包括 BLOB 不存在或无效的情况。
import sqlite3 from contextlib import suppress with sqlite3.connect('errors.db') as conn: conn.execute("CREATE TABLE IF NOT EXISTS resources (id INTEGER, payload BLOB)") try: # Attempt to read non-existent BLOB with conn.blobopen('resources', 'payload', 999, 'main') as blob: data = blob.read() print(f"Read {len(data)} bytes") except sqlite3.OperationalError as e: print(f"Error reading BLOB: {e}") # Insert invalid data (simulate corruption) conn.execute("INSERT INTO resources VALUES (1, 'not a blob')") with suppress(sqlite3.OperationalError): with conn.blobopen('resources', 'payload', 1, 'main') as blob: data = blob.read() print("This won't print for invalid BLOB") print("Cleanup complete")
本示例显示了两种错误情况:读取不存在的行以及尝试读取无效的 BLOB 数据。 第一个使用 try/except,第二个使用 suppress
。
处理 BLOB 时,正确的错误处理至关重要,因为无效数据或丢失的行可能会导致需要捕获和妥善处理的异常。
最佳实践
- 始终使用上下文管理器: 确保适当的资源清理
- 对于大型 BLOB,请分块读取: 避免内存问题
- 检查空 BLOB: 正确处理零长度数据
- 验证偏移量: 防止读取超出 BLOB 边界
- 妥善处理错误: 捕获潜在的 OperationalError
资料来源
作者
列出所有 Python 教程。