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

SQLAlchemy存储DataFrame到PostgreSQL时报can't adapt type 'dict'错误

问题原理

报错can't adapt type 'dict'的核心原因是PostgreSQL的Python驱动psycopg2无法直接识别Python原生的字典、列表嵌套结构,无法将其转换为合法的SQL参数传入数据库。
pandas的to_sql方法默认不会对DataFrame中的复杂Python对象做自动类型适配,当列中存储的是嵌套字典/列表这类非基础类型(字符串、数字、时间等)时,驱动直接拿到原生dict对象就会抛出适配错误。
另外你代码中使用的DataFrame.append()方法已经在Pandas 2.0及以上版本移除,运行时还会触发弃用警告,建议替换为pd.concat()实现行拼接。

实现方案

方案1:整组数据存入单列(匹配原始需求)

PostgreSQL原生支持JSON/JSONB类型存储半结构化数据,你只需要提前将列中的Python对象序列化为标准JSON格式,同时在写入时指定对应列的字段类型即可,代码如下:

import pandas as pd
import json
from sqlalchemy import create_engine, JSON

# 构造测试数据
info_teamdata_df = pd.DataFrame(columns=['Team_1_bans'])
my_dict = {'Team_1_bans': [
    {'championId': 99, 'pickTurn': 1},
    {'championId': 17, 'pickTurn': 2},
    {'championId': 360, 'pickTurn': 3},
    {'championId': 63, 'pickTurn': 4},
    {'championId': 238, 'pickTurn': 5}
]}
# 替换已弃用的append方法
info_teamdata_df = pd.concat([info_teamdata_df, pd.DataFrame([my_dict])], ignore_index=True)
# 将嵌套列表字典序列化为JSON字符串
info_teamdata_df['Team_1_bans'] = info_teamdata_df['Team_1_bans'].apply(json.dumps)

# 写入数据库
db = create_engine('postgresql://postgres:pass@host/MatchData_DB')
with db.connect() as conn:
    info_teamdata_df.to_sql(
        'Tester',
        conn,
        if_exists='append',
        index=False,
        # 指定列类型为JSON,驱动会自动做类型适配
        dtype={'Team_1_bans': JSON}
    )
    conn.commit()

该方案写入后,Team_1_bans列可以直接使用PostgreSQL的JSON查询语法做字段提取、条件筛选,不需要修改原有数据存储逻辑。如果追求更高的查询性能,可以将dtype指定为JSONB(SqlAlchemy中对应JSONB类型)。

方案2:结构化存储(更优实践)

如果后续需要频繁对ban位的英雄、选位顺序做统计查询,不建议将整组数据塞到单个JSON列中,建议将嵌套结构拆分为结构化的行存储,表结构更清晰,查询性能更高,代码如下:

import pandas as pd
from sqlalchemy import create_engine, Integer, String

# 原始嵌套数据
raw_bans = [
    {'championId': 99, 'pickTurn': 1},
    {'championId': 17, 'pickTurn': 2},
    {'championId': 360, 'pickTurn': 3},
    {'championId': 63, 'pickTurn': 4},
    {'championId': 238, 'pickTurn': 5}
]
# 拆分为结构化DataFrame
structured_df = pd.DataFrame(raw_bans)
# 补充所属队伍字段,实际业务中还可以补充对局ID等关联字段
structured_df['team'] = 'Team_1'

db = create_engine('postgresql://postgres:pass@host/MatchData_DB')
with db.connect() as conn:
    structured_df.to_sql(
        'team_ban_records',
        conn,
        if_exists='append',
        index=False,
        dtype={
            'championId': Integer,
            'pickTurn': Integer,
            'team': String(16)
        }
    )
    conn.commit()

该方案下可以直接对championId、pickTurn等字段加索引,统计类查询的写法更简单,执行效率远高于JSON字段查询。

同类问题排查规则

后续遇到同类can't adapt type 'xxx'报错时,统一按照以下逻辑处理即可:

  • 报错本质是psycopg2驱动无法将传入的Python对象转换为PostgreSQL支持的字段类型
  • 处理路径二选一:
    • 提前将Python对象转换为驱动支持的基础类型,比如将dict/list转JSON字符串、将numpy数值类型转Python原生int/float
    • 通过to_sql的dtype参数显式指定字段类型,告知驱动对应的转换规则

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 22:33:01