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() 不再访问 view | view 需要改用 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 稳定版就更有把握。如果问题集中爆出来,说明候选版的价值也达到了:把坑拦在稳定版之前。
