使用psycopg2的copy_from导入CSV到PostgreSQL报错如何解决
报错根因
你触发错误的核心原因是对同一个文件对象混合使用了迭代类方法和读类方法:next(f)会启动文件对象的迭代器逻辑,后续copy_from调用read()方法读取文件内容时,Python会触发保护机制抛出该错误,避免出现数据丢失。
修复方案
方案1:使用copy_from原生参数跳过表头(推荐)
psycopg2 2.8及以上版本的copy_from自带skiprows参数,可直接用来跳过表头行,无需手动操作文件指针,修改后代码如下:
import psycopg2 conn = psycopg2.connect(database="你的库名", user="你的用户名", password="你的密码", host="你的地址", port=你的端口) cur = conn.cursor() with open('21.csv', 'r') as f: # 去掉next(f),用skiprows参数跳过第1行表头 # 如果CSV中不包含id字段(id为数据库自增),需要额外添加columns参数指定除id外的17个字段名,如 # cur.copy_from(f, 'temp_questions', sep=',', skiprows=1, columns=['col1','col2',...,'col17']) cur.copy_from(f, 'temp_questions', sep=',', skiprows=1) conn.commit() cur.close() conn.close()
如果你的CSV文件已经包含id字段,和表的18个字段顺序完全匹配,不需要加columns参数即可直接运行。
方案2:使用copy_expert执行原生COPY语句(兼容性更强)
如果你的psycopg2版本较低不支持skiprows参数,或者CSV包含特殊格式(比如引号包裹字段、自定义空值标识等),可以使用copy_expert直接调用PostgreSQL原生COPY语法,兼容性更好:
import psycopg2 conn = psycopg2.connect(database="你的库名", user="你的用户名", password="你的密码", host="你的地址", port=你的端口) cur = conn.cursor() with open('21.csv', 'r') as f: # CSV HEADER参数会自动跳过表头行,DELIMITER指定分隔符 # 同样如果不需要插入id字段,可以在表名后指定插入列:COPY temp_questions(col1,col2,...) FROM ... cur.copy_expert("COPY temp_questions FROM stdin WITH (FORMAT csv, DELIMITER ',', HEADER);", f) conn.commit() cur.close() conn.close()
注意事项
- 插入前请确认CSV字段顺序和表的字段顺序(或你指定的插入列顺序)完全一致,避免数据错位
- 如果CSV存在换行、逗号等嵌入在字段值里的特殊字符,使用方案2的原生CSV格式解析会比copy_from默认的文本解析更稳定
- 首次测试可以先把
conn.commit()替换为conn.rollback(),验证插入逻辑没问题后再执行提交,避免产生脏数据
内容的提问来源于stack exchange,提问作者keerthana
相关产品推荐
相关产品推荐

