使用psycopg2导入CSV分类数据时触发IndexError问题排查
解决psycopg2插入数据时的IndexError问题
我尝试用psycopg2把CSV文件里的一列数据导入数据库,CSV的genres列格式是用|分隔的多个分类,比如Rock|Pop|Metallic Doom Rock。我先逐行读取值,按|分割后把所有元素加入列表,再用集合去重转成列表保证唯一性。但遍历列表插入SQL时,出现了IndexError: string index out of range错误,代码和错误信息如下:
test = csv_to_dict("artists.csv", "\t") # 基于csv.dictReader的预定义函数,读取制表符分隔的CSV genre_list =[] for row in test: genres = (row['genres']) genres = (genres.split(sep="|")) # 清洗数据生成分类列表 for p in genres: genre_list.append(p.title()) genre_list = list(set(genre_list)) genre_list.sort() cur = sql_con.cursor() sql = 'INSERT INTO Genre (GenreName) VALUES(%s);' # 期望将genre_list中的分类插入到%s位置 for genre in genre_list: cur.execute(sql, genre) sql_con.commit()
错误信息:
Traceback (most recent call last): File "/Users/.../IngestData.py", line 76, in <module> cur.execute(sql, t) IndexError: string index out of range
错误原因
psycopg2的cursor.execute()方法要求第二个参数是序列(元组/列表)或映射。你直接传入单个字符串时,psycopg2会把字符串当作字符序列处理——它会迭代字符串的每个字符,试图匹配SQL中的占位符数量。但你的SQL只有一个%s占位符,字符数量和占位符数量不匹配,因此抛出IndexError。
修复代码
把单个字符串包装成元组(注意末尾的逗号,确保它被识别为元组而非单个元素):
cur = sql_con.cursor() sql = 'INSERT INTO Genre (GenreName) VALUES(%s);' for genre in genre_list: # 将genre放入元组后传入 cur.execute(sql, (genre,)) sql_con.commit()
额外优化建议
- 过滤空分类:如果CSV中存在空的genres值,或者分割后产生空字符串(比如
Rock||Pop分割后会有空元素),可以在添加到列表时过滤掉:
for p in genres: cleaned_p = p.strip().title() if cleaned_p: # 仅添加非空的分类 genre_list.append(cleaned_p)
- 批量插入提升效率:如果genre_list数据量较大,用批量插入代替循环单条插入能显著提升效率:
# 生成批量插入的SQL模板 sql = 'INSERT INTO Genre (GenreName) VALUES %s;' # 将每个genre包装成元组,组成批量插入的参数列表 values = [(genre,) for genre in genre_list] # 使用psycopg2的批量插入工具 from psycopg2.extras import execute_values execute_values(cur, sql, values) sql_con.commit()
内容的提问来源于stack exchange,提问作者Sp1r1tgolem
相关产品推荐
相关产品推荐

