selfdb:用Python对象直接操控PostgreSQL的极简数据库层

> selfdb 是一个用 Python 对象直接映射 PostgreSQL 查询结果的极简数据库访问层,让数据库操作像操作普通 Python 对象一样自然。 ## 痛点:ORM 之重与裸 SQL 之痛 在 Python 生态中,访问数据库主要有两条路: 1. **裸 SQL + 游标**:直接使用 `psycopg2` 或 `asyncpg` 执行 SQL 语句,然后手动处理返回的元组或字典。这种方式灵活、性能最好,但代码冗长且容易出错——你需要自己管理游标、处理类型转换、拼接查询条件,而且结果集是简单的 `dict` 或 `tuple`,无法获得 IDE 自动补全和类型提示。 2. **重型 ORM**:如 SQLAlchemy、Django ORM。它们提供了完整的对象关系映射、迁移工具、会话管理、关联加载等功能,但也带来了巨大的学习曲线和性能开销。很多场景下你只是想做一次简单的查询,却要引入整个 ORM 的复杂生命周期,而且 ORM 生成的 SQL 往往不如手写的精确。 此外,还有一个隐藏的痛点:**数据库连接池和游标生命周期管理**。`psycopg2` 的裸用法要求你手动处理连接、提交、回滚、关闭,稍有不慎就会造成连接泄漏。 selfdb 试图在这两个极端之间找到一条中间路线:**保留 SQL 的灵活性和性能,但去掉所有样板代码,并让结果集自动变成 Python 对象**。 ## selfdb 是什么? selfdb(Self-Database)是一个基于 `psycopg2` 的薄封装层,核心思想非常简单: - 你写 SQL,但不需要管游标和连接细节。 - 查询结果自动转换为 Python 对象,属性名对应列名。 - 支持链式调用、自动提交、上下文管理器,代码量减少 50% 以上。 它的灵感来自 Rust 的 `sqlx` 和 Go 的 `sqlc`——都是“轻量但类型安全”的数据库访问方式,但 selfdb 更贴近 Python 的动态特性。 ## 快速上手 ### 安装 bash pip install selfdb 需要 Python 3.8+,且本机有 PostgreSQL 服务。 ### 基础用法 假设你有一个数据库 `testdb`,其中有表 `users`(id, name, email)。 python import selfdb # 1. 建立连接(全局配置一次即可) selfdb.configure( host='localhost', port=5432, database='testdb', user='postgres', password='secret' ) # 2. 查询——返回对象列表 db = selfdb.Database() users = db.query("SELECT id, name, email FROM users WHERE id > %s", 10) for u in users: print(u.id, u.name, u.email) # 直接访问属性,不再是 dict # 3. 插入、更新、删除——自动提交(可关闭) db.execute("INSERT INTO users (name, email) VALUES (%s, %s)", 'Alice', 'alice@example.com') # 默认自动 commit,无需手动调用 # 4. 事务控制 with db.transaction(): db.execute("UPDATE users SET name = %s WHERE id = %s", 'Bob', 1) db.execute("DELETE FROM users WHERE id = %s", 2) # 事务块内自动 commit/rollback ### 核心亮点:对象映射与动态属性 selfdb 最独特的特性是**结果集自动映射为动态对象**。它不依赖任何 schema 定义或模型类,而是利用 Python 的 `__dict__` 和 `namedtuple` 机制,按列名生成属性。这意味着: - 你不需要预先定义 `User` 类。 - 列名就是属性名,IDE 可以自动补全(因为对象类型是动态的,但你可以通过类型注解辅助)。 - 嵌套查询、JOIN 结果也能自然映射(冲突列名会加上表名前缀)。 例如: python rows = db.query("SELECT u.id, u.name, o.total FROM users u JOIN orders o ON o.user_id = u.id") for r in rows: print(r.id, r.name, r.total) # 无需关心来源表 ### 高级特性:查询构建器(可选) 虽然 selfdb 主打裸 SQL,但它也提供了一个轻量的查询构建器,用于动态拼接条件: python from selfdb import Query q = Query("users") q.filter(id__gt=10).filter(name__like="%A%").order_by("-id") rows = q.all() # 生成 SQL 并执行 这个构建器非常克制,只处理最常见的 WHERE、ORDER BY、LIMIT,不涉及 JOIN 和子查询——那些场景你直接写 SQL 更清晰。 ## 核心亮点总结 1. **极简 API**:只有 `query`、`execute`、`transaction` 三个核心方法,学习成本几乎为零。 2. **自动对象映射**:告别 `row[0]` 或 `row['name']`,直接 `row.name`,代码更可读。 3. **自动提交与事务上下文**:默认自动提交,事务用 `with` 块管理,杜绝连接泄漏。 4. **类型安全(可选)**:通过 Python 3.9+ 的 `TypeVar` 和泛型,你可以让 `query` 返回指定类型,获得静态检查支持。 5. **零依赖**:只依赖 `psycopg2-binary`,无其他安装负担。 6. **性能接近裸 SQL**:没有 ORM 的映射开销和查询生成开销,只比手写游标多一层薄封装。 ## 适用场景 - **微服务**:每个服务只需简单的 CRUD,不需要完整 ORM。 - **数据分析脚本**:快速从 PostgreSQL 拉取数据,直接处理成对象。 - **已有复杂 SQL 的项目**:你不想重写业务逻辑为 ORM 风格,只想把结果集变成对象。 - **教学与原型开发**:快速验证想法,不必陷入 ORM 配置。 - **性能敏感但对裸 SQL 感到繁琐的场景**:selfdb 避免了 ORM 的 N+1 查询问题,因为一切 SQL 由你掌控。 ## 与其他项目对比 | 特性 | selfdb | SQLAlchemy Core | SQLAlchemy ORM | psycopg2 裸用 | |------|--------|----------------|----------------|---------------| | 学习曲线 | 极低 | 中等 | 高 | 低 | | 结果类型 | 动态对象 | Row/字典 | 模型实例 | 元组/字典 | | SQL 控制力 | 完全 | 完全(通过 text()) | 较低(需调优) | 完全 | | 自动提交 | 有 | 需手动 | 需手动 | 无 | | 事务管理 | with 块 | 需手动 | Session | 需手动 | | 依赖重量 | 轻(1个包) | 中 | 重 | 轻 | | 类型提示 | 可选泛型 | Row 类型 | 模型类 | 无 | | 适用规模 | 中小型项目 | 中大型 | 大型复杂域 | 任何 | **与 SQLAlchemy Core 对比**:SQLAlchemy Core 提供了类似 `select()` 的表达式语言,但它的学习曲线更陡,且返回的 `Row` 对象是只读的。selfdb 允许你对返回对象直接赋值属性(虽然不建议),更贴近 Python 的动态风格。 **与 Django ORM 对比**:Django ORM 是重量级方案,自带迁移、管理后台、关系加载。selfdb 完全没有这些,它只做一件事:把 SQL 结果变成对象。如果你不需要 Django 全家桶,selfdb 更轻。 **与 asyncpg 对比**:asyncpg 是异步驱动,性能极高,但需要手动处理类型转换和游标。selfdb 是同步的,基于 psycopg2,适合传统 Web 框架(Flask、FastAPI 的同步路由)和脚本。 ## 潜在不足 - **仅支持 PostgreSQL**:不适用于 MySQL、SQLite。 - **同步设计**:不支持 asyncio(如果你用 asyncpg 生态,请另寻他法)。 - **无迁移工具**:你需要自己管理表结构变更。 - **动态对象缺乏严格的类型安全**:虽然可以用泛型,但运行时仍可能因列名拼写错误而崩溃。 - **社区较小**:目前只有 474 个 star,bug 修复和文档完善可能不如大项目及时。 ## 结论 selfdb 是一个“小而美”的工具,它精准地解决了 Python 开发者在数据库访问中的常见痛点:写 SQL 但不想处理游标、想用对象但不想引入 ORM。它适合那些追求简洁、对 SQL 有掌控力、不想被框架绑架的开发者。如果你正在做一个中小型项目,并且使用 PostgreSQL,selfdb 值得一试。 > 项目链接:https://github.com/fzakaria/selfdb
查看工具