使用psycopg2批量插入DataFrame报错:'dict'对象不支持索引
解决psycopg2批量插入DataFrame时的两个错误
Hey there! Let's break down why you're hitting those errors and get your bulk insert working smoothly.
先拆解你遇到的两个问题
- "string index out of range":这个错误是因为你直接把整个
DataFrame传给了execute_values的argslist参数。psycopg2.extras.execute_values期望argslist是可迭代的记录集合(比如元组列表、列表列表),而不是DataFrame对象本身。当它尝试按字符串索引去读取DataFrame时,自然会触发报错。 - "'dict' object does not support indexing":当你用
dataframe.to_dict(orient='records')得到字典列表后,execute_values默认的模板是按位置索引(比如%s)取值,但字典是键值对结构,没法用[0]、[1]这种索引方式访问,所以就出现了这个错误。
两种靠谱的解决方案
方案1:用列表列表作为输入(最简单直接)
把DataFrame转换成列表的列表,让execute_values可以直接按位置匹配列:
import psycopg2 from psycopg2 import sql from psycopg2.extras import execute_values import pandas as pd # 假设你已经有cur(游标)、entity(目标表名)、column_names(列名列表)、dataframe(待插入的DataFrame) try: # 将DataFrame转为列表的列表,每个子列表对应一行数据 records = dataframe.to_numpy().tolist() execute_values( cur=cur, sql=sql.SQL("INSERT INTO {table_name} ({columns}) VALUES %s").format( table_name=sql.Identifier(entity), columns=sql.SQL(', ').join(map(sql.Identifier, column_names)) ), argslist=records, page_size=500 ) # 务必提交事务,否则数据不会持久化到数据库 cur.connection.commit() except Exception as error: print('ERROR: ' + str(error)) # 出错时回滚事务,避免未完成的事务占用资源 cur.connection.rollback()
方案2:用字典列表配合自定义模板
如果你想保留字典的键值对应关系(避免列顺序出错),可以自定义template参数来匹配字典的键:
import psycopg2 from psycopg2 import sql from psycopg2.extras import execute_values import pandas as pd try: # 转为字典列表,每个字典对应一行数据的键值对 records = dataframe.to_dict(orient='records') # 构造模板:每个列对应字典的键,格式为(%(col1)s, %(col2)s, ...) template = sql.SQL("({})").format( sql.SQL(', ').join([sql.SQL('%({})s').format(sql.Identifier(col)) for col in column_names]) ) execute_values( cur=cur, sql=sql.SQL("INSERT INTO {table_name} ({columns}) VALUES %s").format( table_name=sql.Identifier(entity), columns=sql.SQL(', ').join(map(sql.Identifier, column_names)) ), argslist=records, template=template, page_size=500 ) cur.connection.commit() except Exception as error: print('ERROR: ' + str(error)) cur.connection.rollback()
关键提醒
- 一定要记得提交事务,否则插入的数据只会停留在内存中,不会写入数据库。
- 出错时最好回滚事务,避免未完成的事务占用数据库资源。
- 使用
sql.Identifier和sql.SQL构造SQL语句,能有效防止SQL注入,这是psycopg2官方推荐的安全写法。
内容的提问来源于stack exchange,提问作者Cam Westwood
相关产品推荐
相关产品推荐

