TinyDB:纯 Python 的文档数据库

Python 生态里有很多数据库方案,但如果需要的是一个真正轻量的嵌入式数据库,TinyDB 值得了解一下。它用纯 Python 编写,没有任何外部依赖,也不要求安装单独的数据库服务进程。

定位

TinyDB 面向的是小型应用。如果用 SQL 数据库觉得太重、用外部数据库服务器觉得过当,TinyDB 正好能补上这个空缺。数据存在本地 JSON 文件中,应用启动时加载、关闭时写入,整个过程都在进程内完成。

它是文档导向的,和 MongoDB 类似的思路。在 Python 中每个文档就是一个字典,插入数据调用 db.insert({...}),查询用 db.search(...),不需要写 SQL 语句。对 Python 开发者来说,import 进来就能用,几乎没有学习成本。

对比 SQLite,TinyDB 的优势在于没有模式约束。SQLite 需要预先定义表结构、指定字段类型,TinyDB 不需要。存进去的字典长什么样,读出来就是什么样。字段可以随时增删,不受表结构限制。

核心代码只有 1800 行,配套测试 1600 行,测试覆盖率达到 100%。代码量小意味着出问题容易排查,也方便按需修改。

正文顶部截图

查询语法

TinyDB 的查询通过 Python 运算符重载实现,写法直观:

from tinydb import TinyDB, Query

db = TinyDB('/path/to/db.json')
User = Query()

db.search(User.name == 'John')
db.search((User.name == 'John') & (User.age <= 30))
db.search((User.name == 'John') | (User.name == 'Bob'))
db.search(~(User.name == 'John'))

与、或、非逻辑都可以自由组合。除了基础比较操作(等于、不等于、大于、小于),还支持 matches(regex) 正则匹配和 test(func) 自定义过滤。对于简单的数据查询场景,这套接口基本够用。

有个实用的功能是 map 变换,可以在查询时对字段值做计算后再比较:

db.search((User.age.map(lambda x: x + x) == 44))

多表与中间件

一个数据库文件可以创建多个表,每个表管理自己的一组文档,适合不同模块的数据隔离。比如一个表存用户配置,另一个表存运行日志,互不干扰。

中间件机制给存储层增加了弹性。官方提供的 CachingMiddleware 在内存中缓存读取结果,减少重复的磁盘 I/O。有特殊需求时,也可以自己开发中间件在读写前后插入自定义逻辑。

README区域截图

适用场景

TinyDB 适合数据量不大、单进程、不需要并发写入的场景。桌面应用的配置存储、脚本工具的日志记录、快速原型的数据层,都在它的能力范围内。

Python 版本支持 3.8 到 3.13 以及 PyPy3,覆盖面比较广。

项目目前处于维护模式。作者明确表示不会有大的架构更新,但社区提交的 bug 修复和功能改进仍在持续审查和合并发布。

目前处于维护模式。作者明确表示不会有大的架构更新,但社区提交的 bug 修复和功能改进仍在持续审查和合并发布。

更多推荐