Python字符串拼接失败排查:姓名格式转换脚本中断
问题描述
需求是把“SURNAME, First Names, Religious Title”格式的姓名转换为“First Names Surname”格式。脚本能提取姓名组件,也能把全大写姓氏转成首字母大写,但在字符串拼接(join())环节后触发IndexError,脚本直接中断,输出空的person_cleaned列表。
代码片段
try: for x in range(0, df_length): print(df_length - x) e_df=df.iloc[[x]].fillna("@") # virtual value to avoid issues with empty data frames # CLEAN PERSON NAMES pers_name=e_df['pers_name'].values[0] print(pers_name) if "," in pers_name: pers_new=pers_name.split(",") first_name=pers_new[1].strip() print(first_name) last_name=pers_new[0].title().strip() # change "all caps" to sentence case print(last_name) rel_title=pers_new[2].strip() name_list=(first_name, last_name) try: name_reversed=" ".join(name_list) # religious titles are being ignored print("This is the new name: ", name_reversed) except Exception as e: print(e) else: name_reversed=re.sub("\s\s+" , " ", pers_name) print(name_reversed) person_cleaned.append(name_reversed) except IndexError: print("No more names found.") # add column with cleaned person names print(person_cleaned) print(len(person_cleaned)) df['pers_cleaned']=person_cleaned frame_list.append(df)
输入数据示例
| factoid_ID | pers_ID | pers_name | ... |
|---|---|---|---|
| 5637 | OCR | DORSCH, Anton Joseph | ... |
| 5638 | OCR | DORSCH, Anton Joseph | ... |
| 2006 | OCR | SCHEUICHAVIUS (Schevichavius), Gisbert, SJ | ... |
输出结果
7155 DORSCH, Anton Joseph Anton Joseph Dorsch No more names found. []
问题分析与解决
错误根源
不是join()的问题,问题出在rel_title=pers_new[2].strip()这一行:
- 第一个输入数据
DORSCH, Anton Joseph用逗号分割后,得到的列表是['DORSCH', ' Anton Joseph'],只有2个元素,索引最大是1,直接访问索引2会触发IndexError。 - 你把整个循环都包在了外层的
try-except里,这个错误被捕获后直接跳出了整个循环,导致person_cleaned还没添加任何元素就终止了,所以输出空列表。
修复方案
1. 缩小异常捕获范围,避免一次错误中断全部处理
把外层包裹整个循环的try-except去掉,只在可能出错的地方单独处理,或者提前判断避免出错。
2. 提前判断分割后的列表长度,避免索引越界
在访问pers_new的索引前,先检查列表长度,确保存在对应元素再取值。
修改后的代码
person_cleaned = [] for x in range(df_length): print(df_length - x) e_df = df.iloc[[x]].fillna("@") pers_name = e_df['pers_name'].values[0] print(pers_name) if "," in pers_name: pers_new = pers_name.split(",") # 确保至少有姓氏和名字两部分才处理格式转换 if len(pers_new) >= 2: first_name = pers_new[1].strip() print(first_name) last_name = pers_new[0].title().strip() print(last_name) # 只有存在第三部分时才提取宗教头衔(需求里不需要用到,可忽略) if len(pers_new) >= 3: rel_title = pers_new[2].strip() # 拼接名字,这里join完全没问题 name_reversed = " ".join([first_name, last_name]) print("This is the new name: ", name_reversed) else: # 处理格式不符合的情况,直接保留原姓名 name_reversed = pers_name.strip() else: # 没有逗号的姓名,直接去重空格 name_reversed = re.sub("\s\s+" , " ", pers_name) print(name_reversed) person_cleaned.append(name_reversed) # 后续添加列的代码不变 print(person_cleaned) print(len(person_cleaned)) df['pers_cleaned'] = person_cleaned frame_list.append(df)
关键修改点
- 移除了外层的
try-except,避免单个数据出错导致整个处理中断 - 增加了
len(pers_new)的判断,确保访问索引前元素存在 - 简化了名字拼接的写法,直接用列表传给
join(),效果和元组一致 - 明确处理了不同格式的姓名情况,避免异常
内容的提问来源于stack exchange,提问作者OnceUponATime
相关产品推荐
相关产品推荐

