Python sqlite3.ProgrammingError 异常
上次修改时间:2025 年 4 月 15 日
本综合指南探讨了 Python 的 sqlite3.ProgrammingError 异常,该异常在检测到不正确的 API 使用时发生。 我们将涵盖常见原因、错误处理模式和实际示例。
基本定义
sqlite3.ProgrammingError 是 sqlite3.Error 的一个子类,表示 SQLite 数据库操作中的编程错误。 它通常是由于不正确的 API 使用而不是数据库错误而发生的。
主要特征:它表示开发人员的错误,例如无效的 SQL 语法、不正确的参数绑定或不正确的资源使用。 它在任何 SQL 执行到达数据库引擎之前引发。
无效的 SQL 语法
此示例演示了格式错误的 SQL 语句如何引发 ProgrammingError。 错误发生在执行之前的语句准备期间。
import sqlite3
try:
with sqlite3.connect(':memory:') as conn:
cursor = conn.cursor()
# Missing closing parenthesis
cursor.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT")
except sqlite3.ProgrammingError as e:
print(f"ProgrammingError occurred: {e}")
发生错误的原因是 SQL 语句在语法上不正确。 缺少右括号会在语句准备期间触发异常。
始终在执行之前验证 SQL 语法。 使用 SQL linter 或数据库 GUI 客户端等工具来独立测试查询。
不正确的参数绑定
当由于占位符和参数不匹配而导致参数绑定失败时,会引发 ProgrammingError。
import sqlite3
try:
with sqlite3.connect(':memory:') as conn:
cursor = conn.cursor()
cursor.execute("CREATE TABLE test (id INTEGER, name TEXT)")
# Mismatch between placeholders (2) and parameters (1)
cursor.execute("INSERT INTO test VALUES (?, ?)", (1,))
except sqlite3.ProgrammingError as e:
print(f"Parameter binding error: {e}")
该示例显示了一个常见错误,其中占位符的数量与提供的参数数量不匹配。 错误发生在参数绑定期间。
始终确保参数计数与占位符匹配。 考虑对复杂查询使用命名参数,以提高可读性并减少错误。
已关闭游标的使用
尝试使用已关闭的游标会引发 ProgrammingError。 此示例演示了正确的资源管理。
import sqlite3
with sqlite3.connect(':memory:') as conn:
cursor = conn.cursor()
cursor.execute("CREATE TABLE data (value TEXT)")
cursor.close() # Explicitly close cursor
try:
# Attempt to use closed cursor
cursor.execute("INSERT INTO data VALUES ('test')")
except sqlite3.ProgrammingError as e:
print(f"Closed cursor error: {e}")
尝试使用显式关闭的游标执行 SQL 时发生错误。 游标在关闭后变为无效,无法重复使用。
with 语句在块退出时自动关闭游标。 仅在特定场景(例如长时间运行的连接)中才需要显式关闭。
无效的列操作
尝试对不存在的列或表执行操作时,会发生 ProgrammingError。 此示例显示了正确的错误处理。
import sqlite3
try:
with sqlite3.connect(':memory:') as conn:
cursor = conn.cursor()
cursor.execute("CREATE TABLE products (id INTEGER, name TEXT)")
# Non-existent column 'price'
cursor.execute("SELECT price FROM products")
except sqlite3.ProgrammingError as e:
print(f"Column error: {e}")
发生错误的原因是查询引用了表中不存在的列。 数据库引擎在语句准备期间检测到这一点。
在编写查询之前,始终验证表架构。 必要时使用 PRAGMA table_info 以编程方式检查表结构。
事务管理错误
不正确的事务管理可能会引发 ProgrammingError。 此示例显示了正确的事务处理。
import sqlite3
try:
with sqlite3.connect(':memory:') as conn:
conn.isolation_level = None # Autocommit mode
cursor = conn.cursor()
# Attempt to commit when not in transaction
conn.commit()
except sqlite3.ProgrammingError as e:
print(f"Transaction error: {e}")
发生错误的原因是在没有活动事务时调用了 commit。 在自动提交模式 (isolation_level=None) 下,显式提交是不必要的,并且会引发错误。
了解您的隔离级别设置。 尽可能对事务使用上下文管理器,以避免手动 commit/rollback 调用。
资源清理错误
在不正确的资源清理期间可能会发生 ProgrammingError。 此示例显示了正确的资源管理模式。
import sqlite3
try:
conn = sqlite3.connect(':memory:')
cursor = conn.cursor()
cursor.execute("CREATE TABLE temp (id INTEGER)")
conn.close() # Close connection first
# Attempt to use cursor after connection closed
cursor.execute("SELECT * FROM temp")
except sqlite3.ProgrammingError as e:
print(f"Resource error: {e}")
finally:
cursor.close() # Still need to close cursor
发生错误的原因是在其父连接关闭后使用了游标。 游标依赖于其连接,并在连接关闭时变为无效。
始终以相反的顺序关闭资源:先关闭游标,然后关闭连接。 更好的是,使用上下文管理器来自动处理清理。
类型不匹配错误
ProgrammingError 可以在参数绑定期间发出类型不匹配信号。 此示例演示了正确的类型处理。
import sqlite3
try:
with sqlite3.connect(':memory:') as conn:
cursor = conn.cursor()
cursor.execute("CREATE TABLE items (id INTEGER, data BLOB)")
# Incorrect parameter type for BLOB
cursor.execute("INSERT INTO items VALUES (?, ?)",
(1, "string instead of bytes"))
except sqlite3.ProgrammingError as e:
print(f"Type error: {e}")
发生错误的原因是为 BLOB 列提供了字符串而不是字节。 SQLite 在参数绑定期间执行类型检查。
始终将 Python 类型与 SQLite 列类型匹配。 在绑定之前适当地转换数据,尤其是对于 BLOB 和数字类型。
最佳实践
- 首先验证 SQL: 在编码之前单独测试查询
- 使用参数化查询: 避免语法和注入问题
- 正确管理资源: 一致地使用上下文管理器
- 检查架构: 在查询之前验证表结构
- 专门处理错误: 单独捕获 ProgrammingError
资料来源
作者
列出所有 Python 教程。