使用to_sql上传Pandas DataFrame至Redshift时遇_get_column_info()错误
解决Pandas to_sql上传Redshift时的_get_column_info()错误
我之前在使用Pandas的to_sql往Redshift传数据时也碰到过这个_get_column_info()错误,结合经验总结几个常见的解决方向,你可以逐一排查:
1. 检查依赖版本兼容性
这个错误很多时候是因为Pandas、SQLAlchemy、psycopg2或者sqlalchemy-redshift的版本不匹配导致的,尤其是旧版本的sqlalchemy-redshift在处理Redshift特定数据类型时,会在获取列信息的环节出错。
解决办法:
- 升级所有相关依赖到兼容版本:
pip install --upgrade psycopg2-binary sqlalchemy sqlalchemy-redshift pandas - 注意:如果你的SQLAlchemy版本是2.0及以上,一定要确保sqlalchemy-redshift的版本在2.0.0及以上,否则会有兼容性问题。
2. 处理DataFrame中的特殊数据类型
如果你的DataFrame里存在Redshift不支持的复杂数据类型(比如带时区的datetime64[ns, UTC]、Python对象类型等),to_sql在尝试解析列信息时就会触发这个错误。
解决办法:
- 提前转换不兼容的数据类型:
# 移除datetime列的时区信息 df['your_datetime_col'] = df['your_datetime_col'].dt.tz_localize(None) # 将对象类型转换为字符串类型 df['your_object_col'] = df['your_object_col'].astype(str) - 或者手动指定
dtype参数,强制列类型匹配Redshift支持的类型:from sqlalchemy.types import VARCHAR, TIMESTAMP, INTEGER, DECIMAL dtype_map = { 'id': INTEGER(), 'user_name': VARCHAR(255), 'create_time': TIMESTAMP(), 'amount': DECIMAL(10, 2) } df.to_sql( name='my_table_clean', schema='my_schema', con=conn, index=False, if_exists='replace', chunksize=block_size, dtype=dtype_map )
3. 调整if_exists='replace'的执行逻辑
当目标表已存在时,if_exists='replace'会先删除原表再重建,但Redshift的事务机制、表的特殊约束或者权限问题,可能导致删除表后无法正确获取新表的列信息,从而触发错误。
解决办法:
- 手动删除表后再创建:
from sqlalchemy import text with engine.connect() as conn, conn.begin(): # 先删除原表 conn.execute(text("DROP TABLE IF EXISTS my_schema.my_table_clean")) # 改用if_exists='fail'确保表不存在时才创建 df.to_sql( name='my_table_clean', schema='my_schema', con=conn, index=False, if_exists='fail', chunksize=block_size ) - 或者改用
TRUNCATE清空表后用append插入:with engine.connect() as conn, conn.begin(): conn.execute(text("TRUNCATE TABLE my_schema.my_table_clean")) df.to_sql( name='my_table_clean', schema='my_schema', con=conn, index=False, if_exists='append', chunksize=block_size )
4. 确认Schema和表的权限
如果连接Redshift的用户没有足够的权限(比如无法读取my_schema的表结构、无法删除目标表),_get_column_info()在尝试获取表信息时会失败。
解决办法:
- 执行以下SQL检查用户权限:
-- 检查是否有schema的USAGE权限 SELECT HAS_SCHEMA_PRIVILEGE('your_username', 'my_schema', 'USAGE'); -- 检查是否有目标表的DROP权限 SELECT HAS_TABLE_PRIVILEGE('your_username', 'my_schema.my_table_clean', 'DROP'); - 如果权限不足,联系Redshift管理员为用户添加对应的权限。
内容的提问来源于stack exchange,提问作者Bill
相关产品推荐
相关产品推荐

