You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python2.7操作PostgreSQL时Decimal类型数据被截断问题咨询

精度丢失的根本原因
  • PostgreSQL驱动默认类型转换问题:Python 2.7环境下操作PostgreSQL常用的psycopg2驱动,默认会将数据库的numeric类型字段值自动转换为Python原生float类型。float是双精度浮点数,仅能保存约15~17位有效数字,你存储的高精度小数位数远超这个范围,转换时就会发生精度截断。
  • 隐式类型转换问题:代码中赋值时的兜底默认值为1.0(float类型),即便前面查询到Decimal类型的值,也会因为和float混合使用被隐式转换为float,进一步加重精度丢失。
  • Python 2 float输出截断问题:Python 2中float类型转字符串输出时,会默认截断小数位,导致你看到的导出值比实际float存储的位数还要短。
修复方案
  1. 修改psycopg2的类型映射规则,指定numeric类型返回Decimal而非float,在执行查询前添加类型注册代码即可。
  2. 将兜底默认值替换为Decimal('1.0'),避免隐式类型转换。
  3. 后续需要输出值时,直接操作Decimal类型做格式化,不要转成float后再处理。

修改后代码参考:

from decimal import Decimal
import psycopg2.extensions

def _compute_current_rate(self):
    date = self._context.get('date') or fields.Datetime.now()
    company_id = self._context.get('company_id') or self.env['res.users']._get_company().id
    # 注册numeric类型映射为Decimal
    psycopg2.extensions.register_type(psycopg2.extensions.DECIMAL, self._cr.connection)
    
    query = """SELECT c.id, (SELECT r.rate FROM res_currency_rate r
                              WHERE r.currency_id = c.id AND r.name <= %s
                                AND (r.company_id IS NULL OR r.company_id = %s)
                           ORDER BY r.company_id, r.name DESC
                              LIMIT 1) AS rate
               FROM res_currency c
               WHERE c.id IN %s"""
    self._cr.execute(query, (date, company_id, tuple(self.ids)))
    currency_rates = dict(self._cr.fetchall())
    for currency in self:
        # 兜底值改为Decimal类型
        currency.rate = currency_rates.get(currency.id) or Decimal('1.0')

内容的提问来源于stack exchange,提问作者Kyoungseo Park

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 16:24:03