Python sqlite3.Blob.tell 方法
上次修改时间:2025 年 4 月 15 日
本综合指南探讨了 Python 的 sqlite3.Blob.tell
方法,该方法报告 blob 文件指针的当前位置。我们将涵盖基本用法、实际示例和常用模式。
基本定义
sqlite3.Blob
类表示 SQLite 中的二进制大对象 (BLOB)。它提供对存储在数据库表中的 BLOB 数据的类文件访问。
tell
方法返回 blob 文件指针的当前位置。此位置指示下一次读取或写入操作将在 blob 数据中的何处发生。
Blob tell 基本用法
此示例演示了 tell
方法与 blob 对象的基本用法。 我们创建一个带有 blob 列的表并检查指针位置。
import sqlite3 with sqlite3.connect(':memory:') as conn: conn.execute('CREATE TABLE images (id INTEGER PRIMARY KEY, data BLOB)') # Insert sample blob data blob_data = b'ABCDEFGHIJKLMNOPQRSTUVWXYZ' conn.execute('INSERT INTO images (data) VALUES (?)', (blob_data,)) # Open blob and check position blob = conn.blobopen('images', 'data', 1, 'main') print(f"Initial position: {blob.tell()}") # Output: 0 # Read some data and check new position data = blob.read(5) print(f"After reading 5 bytes: {blob.tell()}") # Output: 5 blob.close()
该示例表明,tell
从 0(blob 的开头)开始,并在我们读取数据时递增。该位置是从 blob 开头开始的字节数。
请始终记住在完成后关闭 blob 对象以释放资源。 with
语句确保数据库连接的正确清理。
写入 Blob 后使用 Tell
此示例演示了写入 blob 时 tell
的行为。我们将创建一个 blob,写入数据并跟踪位置。
import sqlite3 with sqlite3.connect('blobs.db') as conn: conn.execute('CREATE TABLE IF NOT EXISTS documents (id INTEGER PRIMARY KEY, content BLOB)') conn.execute('INSERT INTO documents (content) VALUES (zeroblob(100))') # Open blob for writing blob = conn.blobopen('documents', 'content', 1, 'main') print(f"Start position: {blob.tell()}") # 0 # Write data and check position blob.write(b'Python ') print(f"After write: {blob.tell()}") # 7 blob.write(b'sqlite3.Blob') print(f"After second write: {blob.tell()}") # 19 blob.close()
每个写入操作都会将位置推进写入的字节数。 zeroblob
函数创建一个指定大小的 blob,并用零填充。
当您需要跟踪已写入多少数据或在 blob 数据中实现随机访问模式时,此模式很有用。
Seek 和 Tell 操作
此示例将 seek
与 tell
结合使用,以演示如何在 blob 中导航并跟踪位置变化。
import sqlite3 with sqlite3.connect(':memory:') as conn: conn.execute('CREATE TABLE binaries (id INTEGER PRIMARY KEY, code BLOB)') conn.execute('INSERT INTO binaries (code) VALUES (?)', (b'X' * 1000,)) blob = conn.blobopen('binaries', 'code', 1, 'main') print(f"Initial position: {blob.tell()}") # 0 # Jump to position 500 blob.seek(500) print(f"After seek(500): {blob.tell()}") # 500 # Read 100 bytes data = blob.read(100) print(f"After read(100): {blob.tell()}") # 600 # Seek from current position blob.seek(-50, 1) # Move back 50 bytes from current position print(f"After relative seek: {blob.tell()}") # 550 blob.close()
该示例显示了 tell
如何准确地反映来自绝对和相对 seek 的位置变化。 seek
的第二个参数控制参考点(0=开始,1=当前,2=结束)。
此技术对于实现复杂的 blob 访问模式至关重要,在这种模式下,您需要跳转到二进制数据中的特定位置。
Tell 与大型 Blob
此示例演示了 tell
在大型 blob 中的行为,表明它始终如一地工作,而与 blob 大小无关。
import sqlite3 import random # Generate 5MB of random data large_data = bytes(random.getrandbits(8) for _ in range(5 * 1024 * 1024)) with sqlite3.connect('large_data.db') as conn: conn.execute('CREATE TABLE IF NOT EXISTS big_files (id INTEGER PRIMARY KEY, payload BLOB)') conn.execute('INSERT INTO big_files (payload) VALUES (?)', (large_data,)) blob = conn.blobopen('big_files', 'payload', 1, 'main') chunk_size = 1024 * 1024 # 1MB chunks total_read = 0 while True: data = blob.read(chunk_size) if not data: break total_read += len(data) print(f"Current position: {blob.tell()}, Total read: {total_read}") blob.close()
该示例以 1MB 的块处理 5MB 的 blob,显示了即使使用大型数据,tell
如何跟踪确切的位置。无论 blob 大小如何,位置始终准确。
对于非常大的 blob,像这样分块读取比一次读取整个 blob 更节省内存。 tell
帮助监控进度。
Tell 与空 Blob
此示例显示了 tell
在空 blob 和零长度读取/写入中的行为。
import sqlite3 with sqlite3.connect(':memory:') as conn: conn.execute('CREATE TABLE empty_blobs (id INTEGER PRIMARY KEY, empty BLOB)') conn.execute('INSERT INTO empty_blobs (empty) VALUES (?)', (b'',)) blob = conn.blobopen('empty_blobs', 'empty', 1, 'main') print(f"Initial position: {blob.tell()}") # 0 # Attempt to read from empty blob data = blob.read(10) print(f"After read attempt: {blob.tell()}") # 0 # Write to empty blob blob.write(b'data') print(f"After write: {blob.tell()}") # 4 blob.close()
对于空 blob,tell
从 0 开始。尝试从空 blob 读取不会改变位置。写入数据会按预期推进位置。
在处理数据库架构中可能为空的可选 blob 字段时,了解此行为非常重要。
Tell 与只读模式下的 Blob
此示例演示了以只读模式打开 blob 时 tell
的行为。
import sqlite3 with sqlite3.connect('readonly.db') as conn: conn.execute('CREATE TABLE IF NOT EXISTS logs (id INTEGER PRIMARY KEY, entries BLOB)') conn.execute('INSERT INTO logs (entries) VALUES (?)', (b'log entry 1\nlog entry 2',)) # Open blob in readonly mode (set readable=False) blob = conn.blobopen('logs', 'entries', 1, 'main', readable=True, writable=False) print(f"Initial position: {blob.tell()}") # 0 # Read first line first_line = blob.read(11) print(f"After reading first line: {blob.tell()}") # 11 # Attempting to write would raise sqlite3.OperationalError try: blob.write(b'new data') except sqlite3.OperationalError as e: print(f"Write failed: {e}") blob.close()
在只读模式下,tell
对于读取操作正常工作,但禁止写入。位置仅因读取操作而改变。
当您需要确保 blob 数据不会被意外修改,同时仍然需要读取和跟踪数据中的位置时,这非常有用。
Tell 与多个 Blob 操作
最后一个示例在更复杂的场景中显示了 tell
,其中包含多个操作和位置检查。
import sqlite3 with sqlite3.connect('complex.db') as conn: conn.execute('''CREATE TABLE IF NOT EXISTS records ( id INTEGER PRIMARY KEY, header BLOB, payload BLOB)''') # Insert record with header and payload conn.execute('INSERT INTO records (header, payload) VALUES (?, ?)', (b'HEADER', b'PAYLOAD' * 100)) # Open both blobs header_blob = conn.blobopen('records', 'header', 1, 'main') payload_blob = conn.blobopen('records', 'payload', 1, 'main') # Process header print(f"Header start: {header_blob.tell()}") header = header_blob.read() print(f"Header after read: {header_blob.tell()}") # Process payload in chunks chunk_size = 50 while True: pos = payload_blob.tell() chunk = payload_blob.read(chunk_size) if not chunk: break print(f"Read {len(chunk)} bytes at position {pos}") header_blob.close() payload_blob.close()
该示例显示了同时跟踪多个 blob 中的位置。每个 blob 维护其自身的独立位置,tell
会准确地报告该位置。
当处理结构化二进制数据时,此模式很有用,其中不同的部分存储在单独的 blob 列中,但需要一起处理。
最佳实践
- 始终关闭 blob: 使用上下文管理器或显式 close()
- 在操作之前检查位置: 使用 tell() 验证状态
- 与 seek() 结合使用: 用于在 blob 数据中进行精确导航
- 处理错误: 检查无效位置上的 OperationalError
- 对大型 blob 使用块: 使用 tell() 跟踪进度
资料来源
作者
列出所有 Python 教程。