如何使用Python SQLAlchemy与SQLite存储指定精度的浮点数
问题原因
你遇到的Float的precision参数不生效的问题,本质是两个层面的限制:
- SQLite本身是动态类型系统,属于类型亲和的设计,即便你手动写DDL指定
FLOAT(3),SQLite也不会真的限制存储的浮点精度,底层还是存储为8字节双精度浮点数(REAL类型) - SQLAlchemy的SQLite方言实现中,默认会忽略
Float类型的precision参数,所以不会生成带精度的DDL语句
更简便的实现方案
除了你自己实现的TypeDecorator,还有两种更轻量的实现方式:
- 使用
Numeric/DECIMAL类型(最符合原生使用习惯)
SQLAlchemy的Numeric类型原生支持scale参数指定保留小数位数,会自动帮你做精度截断,不需要额外自定义逻辑:
from sqlalchemy import Column, Numeric # precision是数值总位数,scale是保留小数位数,asdecimal=False直接返回浮点数不需要额外转Decimal perf = Column(Numeric(precision=10, scale=3, asdecimal=False))
这种写法和你之前期望的Float(3)用法几乎一致,是最简便的方案。
- 列级别事件监听
如果不想改字段类型,可以给对应字段加set事件监听,赋值时自动做精度处理,不需要自定义类型也不需要改业务代码:
from sqlalchemy import event from your_module import YourModel @event.listens_for(YourModel.perf, 'set') def auto_round_perf(target, value, oldvalue, initiator): return round(value, 3) if value is not None else value
关于你实现的TypeDecorator的说明
你自己写的PrecisionFloat其实不是冗余实现,而是SQLAlchemy官方推荐的自定义类型标准写法,如果你项目里有多个字段需要统一配置精度,这个自定义类型的复用性更高,反而比每个字段单独配置更高效,完全符合最佳实践。
内容的提问来源于stack exchange,提问作者mibm
相关产品推荐
相关产品推荐

