ZetCode

Python sqlite3.Cursor.setoutputsize 方法

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

本指南探讨了 Python 的 sqlite3.Cursor.setoutputsize 方法,该方法是 DB-API 2.0 规范的一部分,但在 SQLite 中未实现。

基本定义

setoutputsize 方法在 Python 的 DB-API 2.0 规范中定义,用于数据库游标。它旨在预先定义内存分配。

在 SQLite 的实现中,此方法存在但不执行任何操作。 提供它只是为了与其他可能使用此功能的数据库系统实现 API 兼容。

方法签名

该方法具有以下签名:setoutputsize(size, column=None)。两个参数都是可选的。

size 指定预期的输出大小(以字节为单位)。 column 可以指定特定的列索引。 该方法在所有情况下均返回 None。

基本用法

此示例显示了调用该方法的基本语法,尽管它在 SQLite 中无效。

basic_usage.py
import sqlite3

with sqlite3.connect(':memory:') as conn:
    with conn.cursor() as cur:
        # This call does nothing in SQLite
        cur.setoutputsize(1024)  # 1KB expected output
        
        cur.execute("CREATE TABLE test (data TEXT)")
        cur.execute("INSERT INTO test VALUES ('Sample data')")
        conn.commit()
        
        cur.execute("SELECT * FROM test")
        print(cur.fetchone())  # ('Sample data',)

setoutputsize 调用存在,但不影响查询结果或内存使用。 该方法仅出于 API 兼容性而存在。

带列参数

此示例演示了使用可选的列参数,该参数在 SQLite 中也无效。

with_column.py
import sqlite3

with sqlite3.connect(':memory:') as conn:
    with conn.cursor() as cur:
        # Specify output size for column 0
        cur.setoutputsize(2048, 0)  # No effect
        
        cur.execute("""CREATE TABLE products
                     (id INTEGER, name TEXT, price REAL)""")
        
        data = [(1, 'Laptop', 999.99),
                (2, 'Phone', 699.99)]
        cur.executemany("INSERT INTO products VALUES (?, ?, ?)", data)
        
        cur.execute("SELECT * FROM products")
        for row in cur:
            print(row)

列索引参数(在本例中为 0)将指定为支持此功能的数据库预先分配内存的列。

在事务中

此示例显示了在事务块中调用该方法。

in_transaction.py
import sqlite3

with sqlite3.connect('transactions.db') as conn:
    conn.isolation_level = 'EXCLUSIVE'
    with conn:
        cur = conn.cursor()
        cur.setoutputsize(4096)  # Still no effect
        
        cur.execute("CREATE TABLE IF NOT EXISTS logs (message TEXT)")
        cur.execute("INSERT INTO logs VALUES ('Transaction started')")
        
        # The transaction commits automatically when exiting 'with' block

即使在显式事务中,该方法也不会影响 SQLite 的行为。 无论此调用如何,事务都会正常进行。

带有大数据

此示例尝试将该方法与潜在的大数据一起使用。

large_data.py
import sqlite3

with sqlite3.connect(':memory:') as conn:
    with conn.cursor() as cur:
        # Try to pre-allocate for large BLOB
        cur.setoutputsize(10*1024*1024)  # 10MB
        
        # Create table with BLOB column
        cur.execute("CREATE TABLE blobs (id INTEGER, data BLOB)")
        
        # Insert 5MB of data
        data = b'\x01' * 5*1024*1024
        cur.execute("INSERT INTO blobs VALUES (1, ?)", (data,))
        
        cur.execute("SELECT data FROM blobs WHERE id = 1")
        retrieved = cur.fetchone()[0]
        print(f"Retrieved {len(retrieved)//1024}KB of data")

SQLite 处理大型 BLOB 数据,而无需预先分配提示。 在这种情况下,方法调用不会影响内存使用或性能。

多次调用

此示例显示了使用不同参数多次调用该方法。

multiple_calls.py
import sqlite3

with sqlite3.connect('example.db') as conn:
    with conn.cursor() as cur:
        # Multiple calls with different sizes
        cur.setoutputsize(1024)
        cur.setoutputsize(2048, 0)
        cur.setoutputsize(4096, 1)
        
        cur.execute("""CREATE TABLE IF NOT EXISTS measurements
                     (timestamp TEXT, value REAL, unit TEXT)""")
        
        import time
        current_time = time.strftime('%Y-%m-%d %H:%M:%S')
        cur.execute("INSERT INTO measurements VALUES (?, ?, ?)",
                   (current_time, 23.5, 'Celsius'))
        
        cur.execute("SELECT * FROM measurements")
        print(cur.fetchall())

允许对该方法进行多次调用,但没有累积效果。 每个调用实际上都被 SQLite 驱动程序忽略。

使用自定义行工厂

此示例将该方法与自定义行工厂结合在一起。

with_row_factory.py
import sqlite3

def dict_factory(cursor, row):
    return {col[0]: row[idx] for idx, col in enumerate(cursor.description)}

with sqlite3.connect(':memory:') as conn:
    conn.row_factory = dict_factory
    with conn.cursor() as cur:
        cur.setoutputsize(512)  # No effect on row factory
        
        cur.execute("CREATE TABLE books (title TEXT, author TEXT, year INTEGER)")
        cur.execute("INSERT INTO books VALUES (?, ?, ?)",
                   ('Python Cookbook', 'David Beazley', 2013))
        
        cur.execute("SELECT * FROM books")
        print(cur.fetchone())  # {'title': 'Python Cookbook', ...}

无论 setoutputsize 调用如何,自定义行工厂都可以正常工作。 该方法不会以任何方式与行工厂行为交互。

错误情况

此示例表明该方法不会因无效参数而引发错误。

error_cases.py
import sqlite3

with sqlite3.connect(':memory:') as conn:
    with conn.cursor() as cur:
        # These calls are all accepted but do nothing
        cur.setoutputsize(-100)  # Negative size
        cur.setoutputsize(0)
        cur.setoutputsize(1.5)  # Float size
        cur.setoutputsize(100, -1)  # Invalid column
        cur.setoutputsize(100, 1000)  # Out of bounds column
        
        cur.execute("SELECT 1")
        print(cur.fetchone())  # (1,)

SQLite 实现接受没有任何验证的任何参数,因为该方法实际上不执行任何操作。 这与其他一些数据库系统不同。

最佳实践

资料来源

作者

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

列出所有 Python 教程