DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

psycopg2 导入 pandas 报 can’t adapt type numpy.int64:在参数边界转换标量

psycopg2 从 pandas 导入时无法适配 numpy.int64,应检查最终参数并按已验证的整数字段转换为 Python int。保留参数绑定,区分缺失值、整数范围、精度和批次事务。

pandas 表格中 id_code 看起来是整数,PostgreSQL 列也已定义为整数,但 psycopg2.executemany 仍报 can't adapt type 'numpy.int64'。先检查实际传入参数的 Python 类型:表格中的 NumPy 标量不一定是驱动直接支持的 Python int。

psycopg2 按 Python 对象类型选择适配方式。numpy.int64 缺少对应适配时,修改数据库列为 BIGINT 不会让这个对象自动变成 Python int。本文针对 psycopg2 的参数适配;其他驱动版本的类型支持需分别核对。

看提交的对象,不只看 DataFrame.dtype

在受控诊断范围内,从即将提交的参数中取一个目标字段,只查看 type,不必输出数值或整行业务数据。原 DataFrame 的 dtype、转换后表格的 dtype 和最终参数的对象类型是三个检查位置。

调用 astype(int) 通常仍是在选择 NumPy 数组的整数类型。随后经 to_records 等路径取值,仍可能得到 numpy.int64 或其他 NumPy 标量。换一个批量遍历方法也不代表所有列、所有版本都会转换为相同 Python 类型,应检查最终参数。

如果错误里是 numpy.ndarray,那是数组对象,需要明确目标列是数组、向量还是单个标量,不能把整份数组交给 int 处理。若错误改成数值越界、非空约束失败,说明又到了不同的数据校验阶段。

在明确的整数字段边界转换

对于已经确认应当保存整数的字段,可在构造参数时使用 Python int。下面是局部示例:df 只选取 id_code 和 sector 两列,sector 已由业务校验为驱动支持的字符串;id_code 不允许缺失、布尔值或非整数:

import numpy as np


def normalize_id(value):
    if isinstance(value, (bool, np.bool_)):
        raise TypeError("id_code must be an integer, not boolean")
    if not isinstance(value, (int, np.integer)):
        raise TypeError("id_code must be a validated integer")
    return int(value)


rows = [
    (normalize_id(code), sector)
    for code, sector in df[["id_code", "sector"]].itertuples(
        index=False, name=None
    )
]

这里故意不把浮点数、字符串或缺失值直接交给 int,避免截断小数或把数据错误悄悄变成另一个 ID。目标 PostgreSQL 列仍有自己的整数范围,Python int 可以容纳更大的值,不代表数据库也一定接收。

对确定的整数 NumPy 标量也可采用相应的标量取值方法,但不要把 item 当作通用类型清洗器:object 数组可能原样返回其中的对象,某些精度类型没有对应的普通 Python 标量。批量转换应围绕实际列含义设计。

仍用参数绑定,并保持事务处理

在已有 cursor 和项目事务范围中,写入片段可采用以下形式。classification 与列名是已确认的实际结构示例,不来自用户输入:

cur.executemany(
    "INSERT INTO classification (id_code, sector) VALUES (%s, %s)",
    rows,
)

%s 是 psycopg2 的值占位符,不要改成 %d,也不要用格式化字符串或拼接将值写进 SQL。类型转换与安全的参数绑定需要一起保留。

在整批参数准备和校验完成后再提交写入,按项目设计决定整批提交或分批提交。发生异常时,沿既有事务失败路径回滚;不要捕获异常后直接声称本批完成,也不要对可能已提交的批次无条件重放。

注册自定义适配器是另一种方案,但会改变相关类型在注册范围内的处理方式,需要明确缺失值、精度、SQL 表示及其他调用方的行为。只有少数明确字段需要转换时,局部参数边界通常更容易核对,不必为了这一次导入给所有 NumPy 值统一套用 AsIs。

缺失值与数值精度另行确定

NaN、pandas 缺失标记和 SQL NULL 不是可以随意互换的整数。若字段允许缺失,应在业务规则确认后将对应标量转换为 None;不允许缺失则应在写入前拒绝或按规定补齐。别用零掩盖缺失 ID。

也不要为了适配将整数 ID 整列转成 float,较大的整数可能失去精度。价格等精确小数需采用适合业务的十进制类型与校验,不能把所有无法适配的对象一律 int 或 float。

处理后在隔离数据中检查实际参数类型、正常行、缺失值、布尔值及接近目标列边界的整数,再核对写入与读回值。成功标准包括不再出现适配错误、行数符合预期,且整数没有被截断、舍入或替换。

修改前保留导入代码、输入数据与批次记录。需要回退时恢复转换逻辑,并核对已提交的导入批次;恢复代码不会自动撤销数据,应通过已有批次身份或数据恢复流程纠正。