SQLite3连接时路径错误会静默创建新库而非报错,需用绝对路径或确认工作目录,连接后应查sqlite_master验证表存在,并显式commit写操作。

SQLite3连接数据库时,文件路径写错会导致静默创建新库
默认情况下,sqlite3.connect() 如果指定的.db文件不存在,会自动创建一个空数据库——而不是报错。这常导致你以为在操作旧数据,实际却在往全新库写入。
- 检查路径是否为绝对路径或相对于当前工作目录的正确相对路径;用
os.path.abspath("data.db")确认真实位置 - 连接后立即执行
cursor.execute("SELECT name FROM sqlite_master WHERE type='table';").fetchall(),确认表是否存在 - 开发阶段建议加一层存在性校验:
if not os.path.exists("data.db"):提示用户初始化
INSERT语句不生效?大概率是忘了commit()或用了错误的占位符语法
SQLite3默认开启事务,所有写操作必须显式调用 conn.commit() 才会持久化。另外,Python的参数化查询只支持 ?(问号)或命名占位符(:name),混用 %s 会直接拼接字符串,引发SQL注入或语法错误。
- 写操作后务必调用
conn.commit();若用上下文管理器(with conn:),会自动commit/rollback - 正确写法:
cursor.execute("INSERT INTO users (name, age) VALUES (?, ?)", ("Alice", 30)) - 错误写法:
cursor.execute(f"INSERT INTO users VALUES ('{name}', {age})")—— 危险且易出错 - 批量插入用
executemany(),性能比循环+execute高数倍
查询结果返回的是tuple,不是dict,字段顺序容易搞混
cursor.execute().fetchone() 返回的是 tuple,按SELECT字段顺序排列。如果SQL里写了 SELECT id, name,取值就得用 row[0]、row[1],一改字段顺序就崩。
- 启用列名访问:在
connect()后设置conn.row_factory = sqlite3.Row - 之后
row["name"]或row[1]都可用,推荐优先用字段名 - 如果需要转成字典,
dict(row)可直接转换(前提是已设row_factory) - 注意:
sqlite3.Row不影响性能,但避免在高频循环中反复调用dict(row)
多线程写入报“database is locked”?别直接共用一个Connection
SQLite本身是线程安全的,但默认连接(Connection)对象**不是**线程共享安全的。多个线程共用一个 conn 并发写,极易触发锁等待超时。
立即学习“Python免费学习笔记(深入)”;
- 每个线程应独立调用
sqlite3.connect()获取自己的连接(轻量,开销不大) - 避免全局
conn变量;如需复用,用threading.local()绑定连接到线程本地 - 写操作尽量短:打开连接 → 执行 → commit → close,不要长期持有
- 读多写少场景可加
timeout=5参数:sqlite3.connect("db.db", timeout=5),避免无限等待


















