Simon Willison 在 2026 年 6 月 21 日发布了 sqlite-utils 4.0rc1。这个版本号里的 rc1 很关键:它是 sqlite-utils v4 的首个 release candidate,不是正式稳定版。

sqlite-utils 是一个面向 SQLite 的 Python 库和 CLI 工具,构建在 Python 标准库 sqlite3 之上。它常用来自动建表、导入 JSON/CSV、转换表结构,也适合写一些轻量但长期运行的数据脚本。

我更在意的不是“v4”这个大版本号,而是两个能力终于被收进主工具:migrations,以及 db.atomic() 嵌套事务。前者更像成熟能力入库,后者更像需要真实项目多踩一轮边界。

rc1 的定位:功能接近定型,但还不该直接上生产

Willison 明确说,这是 v4 的第一个候选版本,并希望用户在稳定版前试用。这个表述说明两件事:功能轮廓基本收束,但作者还在等外部项目验错。

对 sqlite-utils 这类工具来说,rc 阶段的意义不小。它不是一个只给终端用户点按钮的应用,而是会嵌进脚本、CLI 流程和项目初始化逻辑里的开发者工具。一处默认行为变化,可能不会立刻报错,却会改变落库结果。

最该先动手的,是两类人:

使用者建议动作原因
维护 sqlite-utils Python 代码的项目作者在测试库跑现有测试和迁移脚本v4 有少量不兼容变化,尤其是 upsert、view 和类型检测
重度使用 sqlite-utils CLI 导入数据的人用样本 CSV/TSV 试一次导入结果CLI 导入默认类型检测已变化,字段类型可能和旧版本不同

我的判断是,4.0rc1 已经很接近稳定版形态,但它仍然适合“试跑”,不适合无测试地替换生产依赖。尤其是那些把 SQLite 当作应用内数据库、数据处理落盘格式、轻量工具后端的项目,更应该先锁版本、跑样本、看 diff。

migrations 入库:成熟能力收编,但不提供反向迁移

这次最稳的新增能力,是 migrations。

它不是从零写的新实现,而是 sqlite-migrate 的改造移植。sqlite-migrate 是 Willison 几年前发布的包,已经被 LLM 和其他项目使用多年。这个背景很重要:migrations 不是一个刚冒出来的实验接口,而是经过实际项目使用后,被并入 sqlite-utils。

用法也保持得很轻。开发者可以在 migrations.py 里定义一组迁移,用 Python API 执行,也可以直接走 CLI:

sqlite-utils migrate creatures.db migrations.py

这对 sqlite-utils 用户是实在的减负。过去你可能用 sqlite-utils 做表操作,再额外管理迁移包。现在迁移、建表、改列、导入数据,可以更集中地放在同一套工具里。

但它也有一个明确限制:不支持 reverse migrations。

也就是说,迁移写错了,不是让工具自动倒回旧版本,而是再发一个新的迁移去修正。这个设计很克制,也很 SQLite。少一层复杂性,少一层“看起来能回滚”的安全幻觉。

对个人工具、嵌入式应用、本地数据库和数据项目来说,这通常够用。对依赖严格回滚流程、多环境数据库版本对齐、复杂发布审批的团队来说,它可能不够完整。这里不能拿它当 Django、Rails 或 Alembic 那类大型应用迁移系统的平替。

一句话:migrations 入库提升了 sqlite-utils 的可维护性,但它选择的是小而稳,不是大而全。

db.atomic() 和破坏性变更:试用重点在边界行为

另一个新增能力是 db.atomic()

SQLite 本身支持通过 savepoints 实现嵌套事务。db.atomic() 做的事,是把这套能力包装成更顺手的 Python 上下文管理器。外层事务可以继续,内层代码块失败时,只回滚内层操作。

这个命名借鉴了 Django 和 Peewee 的 atomic。熟悉这些框架的开发者,上手成本会低一些。

但这里要更谨慎。Willison 在原文里也提示,db.atomic() 的测试覆盖少于 migrations。换句话说,migrations 更像老能力入库,db.atomic() 更需要真实项目验证。

如果你的代码里有这些场景,建议重点试:批量写入、异常捕获、内外层事务嵌套、封装后的 helper 函数、插件里间接调用数据库写入。问题往往不出在最简单的 demo,而出在这些边界组合里。

v4 还有几项破坏性变更。作者称这是 major bump 对应的较小不兼容变化,但“小”不等于可以忽略。

变化旧行为/影响点升级时该查什么
upsert 语义变化更多使用 SQLite 的 INSERT ... ON CONFLICT SET是否依赖旧的 INSERT OR IGNORE 后再 UPDATE 行为;必要时用 use_old_upsert=True
停止支持 Python 3.8新增支持 Python 3.13项目运行环境是否还卡在 Python 3.8
db.table() 不再访问 viewview 需要改用 db.view()代码里是否把 view 当 table 访问
浮点列类型从 FLOAT 改为 REAL自动检测浮点列时类型不同schema 对比、测试断言、下游读取是否依赖旧类型名
CSV/TSV 导入默认类型检测过去默认更偏向文本导入CLI 导入结果字段类型是否变化;旧行为用 --no-detect-types
convert 不再跳过 False 值以前会跳过求值为 False 的值转换逻辑里是否依赖空值、0、False 被跳过
schema 引号变化新建表改用双引号包裹表名和列名是否有测试直接比对 schema 字符串

试用命令很直接:

pip install sqlite-utils==4.0rc1

如果只想临时跑 CLI,可以用:

uvx --with sqlite-utils==4.0rc1 sqlite-utils --help

接下来最该看的,不是功能清单会不会再加长,而是 rc1 用户会不会在三个地方报问题:upsert 兼容性、CSV/TSV 类型检测、db.atomic() 嵌套事务边界。

如果这些点反馈平稳,v4 稳定版就更有把握。如果问题集中爆出来,说明候选版的价值也达到了:把坑拦在稳定版之前。