Python sqlite3.Blob.__len__ 方法
上次修改时间:2025 年 4 月 15 日
本综合指南探讨了 Python 的 sqlite3.Blob.__len__
方法,该方法返回 BLOB(二进制大对象)的长度(以字节为单位)。我们将介绍基本用法、实际示例和最佳实践。
基本定义
BLOB 是 SQLite 中用于存储二进制数据的数据类型。sqlite3.Blob
类提供对 Python 中 BLOB 数据的访问。__len__
方法返回 BLOB 的大小(以字节为单位)。
主要特性:当在 Blob 对象上使用 len
时调用,返回一个整数,并且仅适用于打开的 Blob 对象。该方法提供有效的尺寸检查,而无需将整个 BLOB 加载到内存中。
基本 BLOB 长度检查
此示例演示了创建具有 BLOB 列的表并使用 __len__
方法检查其长度。
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 binary_data = b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00' conn.execute("INSERT INTO images (data) VALUES (?)", (binary_data,)) # Open BLOB and check length blob = conn.blobopen('images', 'data', 1, 'main') print(f"BLOB length: {len(blob)} bytes") # Calls __len__ blob.close()
此示例创建一个表,插入二进制数据,然后打开 BLOB 以检查其长度。len
函数在内部调用 __len__
。
请注意,我们在使用后正确关闭 BLOB 对象。长度与我们插入的二进制字符串的大小匹配(在本例中为 24 字节)。
检查空 BLOB 长度
此示例显示了 __len__
对空 BLOB 的行为方式。
import sqlite3 with sqlite3.connect('empty_blobs.db') as conn: conn.execute("CREATE TABLE IF NOT EXISTS empty_blobs (id INTEGER PRIMARY KEY, empty_data BLOB)") # Insert empty BLOB conn.execute("INSERT INTO empty_blobs (empty_data) VALUES (?)", (b'',)) # Check length of empty BLOB with conn.blobopen('empty_blobs', 'empty_data', 1, 'main') as blob: print(f"Empty BLOB length: {len(blob)} bytes") # Returns 0
在这里,我们插入一个空字节对象并验证 __len__
返回 0。该示例使用上下文管理器自动关闭 BLOB。
空 BLOB 在 SQLite 中是有效的,可用作占位符或默认值。__len__
方法正确报告了它们的零大小。
比较 BLOB 长度
此示例演示了比较表中多个 BLOB 的长度。
import sqlite3 with sqlite3.connect('compare_blobs.db') as conn: conn.execute("CREATE TABLE IF NOT EXISTS files (id INTEGER PRIMARY KEY, content BLOB)") # Insert files of different sizes small_file = b'small' medium_file = b'medium size content' large_file = b'large' * 1000 conn.executemany("INSERT INTO files (content) VALUES (?)", [(small_file,), (medium_file,), (large_file,)]) # Compare lengths cursor = conn.cursor() cursor.execute("SELECT rowid FROM files ORDER BY rowid") for rowid, in cursor: with conn.blobopen('files', 'content', rowid, 'main') as blob: print(f"File {rowid} size: {len(blob)} bytes")
此代码插入三个不同大小的 BLOB,然后检索每个 BLOB 以比较它们的长度。__len__
方法提供每个 BLOB 的大小。
该示例演示了如何有效地处理多个 BLOB,使用它们的长度进行比较或分析,而无需加载实际内容。
事务中的 BLOB 长度
此示例演示了在事务中检查 BLOB 长度。
import sqlite3 with sqlite3.connect('transaction.db') as conn: conn.execute("CREATE TABLE IF NOT EXISTS documents (id INTEGER PRIMARY KEY, doc BLOB)") # Start transaction with conn: # Insert document doc_content = b'This is a document' * 100 conn.execute("INSERT INTO documents (doc) VALUES (?)", (doc_content,)) # Get last inserted rowid rowid = conn.execute("SELECT last_insert_rowid()").fetchone()[0] # Check length within transaction with conn.blobopen('documents', 'doc', rowid, 'main') as blob: print(f"Document size before commit: {len(blob)} bytes") # Verify length after commit with conn.blobopen('documents', 'doc', rowid, 'main') as blob: print(f"Document size after commit: {len(blob)} bytes")
此示例表明 __len__
在事务内外均可工作。在提交之前和之后,BLOB 长度保持一致。
上下文管理器确保正确的事务处理,同时我们在操作的不同点检查 BLOB 大小。
BLOB 长度的错误处理
此示例演示了使用 __len__
时的错误情况。
import sqlite3 try: with sqlite3.connect('errors.db') as conn: conn.execute("CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, data BLOB)") # Try to get length of closed BLOB blob = conn.blobopen('test', 'data', 1, 'main') blob.close() try: print(len(blob)) # Will raise Error except sqlite3.ProgrammingError as e: print(f"Error: {e}") # Try to get length of non-existent BLOB try: with conn.blobopen('test', 'data', 999, 'main') as blob: print(len(blob)) except sqlite3.OperationalError as e: print(f"Error: {e}") except sqlite3.Error as e: print(f"Database error: {e}")
此示例显示了两种常见的错误情况:在关闭的 BLOB 上调用 __len__
和尝试打开不存在的 BLOB。两者都会引发适当的异常。
在处理 BLOB 时,适当的错误处理至关重要,因为由于各种原因(如连接关闭或无效的 rowid),操作可能会失败。
具有不同数据类型的 BLOB 长度
此示例显示了 __len__
对不同二进制数据的行为方式。
import sqlite3 import pickle with sqlite3.connect('datatypes.db') as conn: conn.execute("CREATE TABLE IF NOT EXISTS objects (id INTEGER PRIMARY KEY, obj BLOB)") # Store different Python objects as BLOBs objects = [ pickle.dumps([1, 2, 3]), # List pickle.dumps({'a': 1}), # Dict pickle.dumps(3.14159), # Float pickle.dumps("Hello"), # String pickle.dumps(True) # Boolean ] conn.executemany("INSERT INTO objects (obj) VALUES (?)", [(o,) for o in objects]) # Check lengths of serialized objects cursor = conn.cursor() cursor.execute("SELECT rowid FROM objects ORDER BY rowid") for rowid, in cursor: with conn.blobopen('objects', 'obj', rowid, 'main') as blob: print(f"Object {rowid} serialized size: {len(blob)} bytes")
此示例使用 pickle 将不同的 Python 对象序列化为 BLOB,并检查它们的大小。__len__
方法报告序列化的大小。
该示例演示了 __len__
可以处理任何二进制数据,无论其原始 Python 类型或内容如何。
只读模式下的 BLOB 长度
此示例演示了将 __len__
与只读 BLOB 一起使用。
import sqlite3 with sqlite3.connect('readonly.db') as conn: conn.execute("CREATE TABLE IF NOT EXISTS archives (id INTEGER PRIMARY KEY, zip_data BLOB)") # Insert sample zip data zip_data = b'PK\x03\x04\x14\x00\x00\x00\x00\x00' # Partial ZIP header conn.execute("INSERT INTO archives (zip_data) VALUES (?)", (zip_data,)) # Open BLOB in read-only mode and check length with conn.blobopen('archives', 'zip_data', 1, 'main', readonly=True) as blob: print(f"ZIP data length: {len(blob)} bytes") try: blob.write(b'new data') # Will fail except sqlite3.OperationalError as e: print(f"Expected error when writing: {e}")
此示例以只读模式打开 BLOB,并验证 __len__
即使没有写权限也能正常工作。尝试修改 BLOB 会引发错误。
当您只需要检查 BLOB 元数据(如大小)而不修改内容时,只读模式非常有用。
最佳实践
- 始终关闭 BLOB 对象: 使用上下文管理器进行自动清理
- 在读取之前检查长度: 避免缓冲区溢出
- 优雅地处理错误: BLOB 操作可能会失败
- 用于大型二进制文件: BLOB 非常适合大型数据
- 考虑内存使用情况: 长度检查不会加载内容
资料来源
作者
列出所有 Python 教程。