在现代 Python 后端开发中,轻量级且高效的数据库交互工具至关重要。本文将总结 psql_utils 库的架构设计与重构过程。这是一个基于 psycopg 3 构建的 PostgreSQL 工具库,旨在提供类型安全、同时支持同步(Sync)与异步(Async)的高级数据操作接口。
1. 项目概览与架构设计
psql_utils 并没有采用全功能的 ORM(对象关系映射)模式,而是选择了一种更轻量级的"SQL 构建器 + 记录操作"模式。这种设计在保持 SQL 灵活性的同时,大大简化了常见的 CRUD 操作。
项目核心由以下几个模块组成:
- 类型定义与 SQL 构建 (
types.py,gen_sql.py) : 负责将 Python 对象转换为 SQL 语句,避免了容易出错的字符串拼接。 - 连接池管理 (
__init__.py,sync.py) : 分别提供了基于asyncio的异步连接池和基于线程的同步连接池,二者共享相似的 API 设计。 - 记录操作抽象 (
record.py,record_sync.py,record_utils.py) : 在 SQL 构建之上封装了get(查询),save(插入/更新),remove(删除) 等高层业务逻辑。 - 打包配置 (
pyproject.toml,setup.py) : 遵循现代 Python 打包标准。
2. 核心重构与优化点
在对代码库的全面审查中,我们实施了严格的 PEP 8 规范,并修复了潜在的运行时错误。以下是本次重构的关键优化点:
A. 修复可变默认参数 (Mutable Default Arguments)
这是 Python 中最常见的陷阱之一。在原代码中,多个函数使用了 list 作为默认参数(例如 keys=[])。这会导致列表对象在函数调用间共享,从而引发难以调试的状态污染 bug。
优化前:
Python
ini
def __init__(self, joins=[]): # 危险!所有实例共享同一个列表
self.joins = joins
优化后:
Python
python
def __init__(self, joins: Optional[List[LeftJoin]] = None):
# 安全:每次初始化都创建新列表
self.joins = joins if joins is not None else []
B. 类型提示与安全性 (Type Hinting)
引入了 typing 模块(Optional, List, Union, Callable),配合 mypy_extensions,极大地增强了代码的可读性和 IDE 的自动补全能力。所有函数签名现在都清晰地表明了输入输出类型,减少了类型相关的运行时错误。
C. 代码风格与规范 (PEP 8 & 79字符限制)
为了适应各种开发环境(包括终端编辑器和分屏开发),我们强制执行了每行不超过 79 个字符的标准。
- 字符串格式化 :将陈旧的
.format()方法全面替换为 Python 3.6+ 的 f-string,不仅代码更短,性能也更优。 - 文档注释:为核心类和函数添加了清晰的英文 Docstrings,解释了参数用途和返回值。
D. 连接池的健壮性
在 __init__.py (Async) 和 sync.py (Sync) 中,使用了装饰器模式 (@run_with_pool) 来自动管理数据库游标(Cursor)的生命周期。
- 自动重连 :当检测到连接断开(如
closing错误)时,装饰器会自动尝试重新建立连接池并重试操作,大大提高了服务在数据库重启或网络波动下的稳定性。
3. 核心功能展示
智能的 SQL 生成
gen_sql.py 处理了复杂的 SQL 拼接逻辑,特别是 UPSERT(插入或更新)操作。
Python
ini
# 自动生成 INSERT INTO ... ON CONFLICT DO UPDATE
sql = gen.gen_insert_or_update(
table_name=t('users'),
uniq_columns=[c('email')],
value_columns=[c('name'), c('age')]
)
统一的 Record API
无论是在异步还是同步环境中,开发者都可以使用几乎一致的 API 来处理数据。
异步保存数据 (record.py):
Python
ini
# 如果 id 存在则更新,否则根据唯一键判断是插入还是更新
user_id = await record.save(
table=t('users'),
uniq_keys=['email'],
email='user@example.com',
name='Pythonista',
json_keys=['meta'] # 自动处理 JSON 序列化与合并
)
同步获取列表 (record_sync.py):
Python
ini
# 支持分页、排序、JSON 字段查询
users = record_sync.get_list(
table=t('users'),
part_sql="meta#>>'{role}' = %s",
args=('admin',),
size=20,
sorts='created_at desc'
)
4. 现代化打包与依赖
项目配置已更新以支持现代 Python 生态:
- pyproject.toml:作为构建系统的核心,指定了构建依赖。
- 依赖管理 :明确声明了
psycopg[binary,pool],确保安装时包含二进制驱动和连接池支持,提升安装速度和运行性能。 - 版本兼容 :明确标记支持 Python 3.8+,并移除了已废弃的
distutils。
总结
经过本次重构,psql_utils 从一个简单的工具脚本集合蜕变为一个健壮、类型安全且易于维护的 Python 库。它既保留了直接操作 SQL 的灵活性,又提供了足够的抽象来加速日常开发,是构建中小型 PostgreSQL 应用的理想选择。