使用psycopg2的copy_from加载Postgres数据时遭遇TypeError问题求助
解决PostgreSQL copy_from报错:TypeError: Expected bytes or unicode string, got quoted_name instead
我之前处理大文件导入PostgreSQL时也踩过类似的坑,咱们来理清楚这个问题的来龙去脉:
问题背景
你需要导入一个900MB的数据集到AWS上的PostgreSQL,用pandas的df.to_sql速度慢到无法接受(超过8小时),于是转向PostgreSQL更高效的copy_from方法,却遇到了这个类型错误:
Traceback (most recent call last): File "sam_monthly_extract.py", line 312, in <module> cur.copy_from(sio, 'sam_monthly_extract_temp', sep=',', columns=load_column_names) TypeError: Expected bytes or unicode string, got quoted_name instead
你一开始怀疑是to_csv的quoting参数导致的,后来把分隔符从逗号改成|解决了地址字段含逗号被引号包裹的问题,但报错依然存在——其实这个错误和CSV的引号处理无关。
报错根源
这个错误的核心原因是**copy_from方法对columns参数的类型要求非常严格**:它要求传入的列名必须是纯字符串组成的列表,但你的load_column_names列表里很可能包含了PostgreSQL的quoted_name对象(比如列名包含特殊字符、大小写敏感,被自动加上了引号标记),copy_from无法识别这种对象,因此抛出类型错误。
最终解决方案
你最后改用copy_expert的思路完全正确!copy_expert通过直接执行完整的COPY SQL语句来操作,绕开了copy_from对列名参数的类型限制,同时还能更灵活地配置CSV的解析规则。
有效代码如下:
sio = StringIO() sio.write(raw_data.to_csv(index=False, header=None, quoting=csv.QUOTE_NONNUMERIC, sep='|')) sio.seek(0) with conn.cursor() as cur: cur.copy_expert("""COPY sam_monthly_extract_temp FROM STDIN WITH (FORMAT CSV, DELIMITER '|')""", sio) conn.commit()
额外优化建议
如果需要指定导入的列顺序,直接在COPY语句里列出来即可:
COPY sam_monthly_extract_temp (column_name_1, column_name_2, column_name_3) FROM STDIN WITH (FORMAT CSV, DELIMITER '|')
另外copy_expert支持更多COPY参数(比如定义NULL值的格式、指定编码等),比copy_from的参数覆盖范围更广,适合复杂的导入场景。
内容的提问来源于stack exchange,提问作者spitfiredd
相关产品推荐
相关产品推荐

