Python代码运行触发KeyError('Birthdate'),求try-except异常处理的具体实现方法
看起来你的问题核心出在输入数据读取环节,当然我也会给你讲清楚try-except的实际用法。先看报错:KeyError: 'Birthdate',这说明你的sample字典里压根没有这个键——不是你取键的方式错了,是生成字典的时候就没把这个键加上。
问题根源
看你的输入文件raw.data.py,每行内容是这种格式:
'Betty:Boop:245-836-8357:635 Cutesy Lane:Hollywood:CA:6/23/1923',
当你用line.strip().split(':')处理时,得到的第一个元素是'Betty(带开头的单引号),最后一个元素是'6/23/1923', (带结尾的单引号、逗号和空格)。更要命的是,如果某些行清理不彻底,split(':')得到的元素数量会和你定义的columns长度(7个)不匹配,这时候zip(columns, row)生成的字典就会缺少后面的键——比如Birthdate直接消失,自然抛出KeyError。
两步解决问题
1. 先修复数据读取逻辑(从根源避免错误)
首先要把每行的多余字符清理干净:去掉首尾的单引号、逗号和空格,确保split后正好得到7个元素,和columns一一对应。修改读取部分的代码:
inputFile = 'raw.data.py' data = list() columns = ['First name','Last name','Telephone','Address','City','State','Birthdate'] for line in open(inputFile): # 跳过注释行 if line.startswith('#'): continue # 清理行首尾的引号、逗号、空格 cleaned_line = line.strip().strip("', ") row = cleaned_line.split(':') # 只保留元素数量和columns一致的行,过滤无效数据 if len(row) == len(columns): data.append(dict(zip(columns, row)))
这样生成的每个sample字典都会包含Birthdate键,从根源上解决KeyError。
2. 学会用try-except处理异常(容错兜底)
如果还是担心有漏网的无效数据,或者想在出错时做自定义处理(比如跳过该行、记录错误日志),可以这样使用try-except:
formatted_data = list() for sample in data: try: # 尝试执行可能抛出异常的代码块 birthdate = sample['Birthdate'] mm,dd,yy = birthdate.split('/') if len(yy)==2: yy = '19' + yy birthdate = '/'.join([mm,dd,yy]) sample['Birthdate'] = birthdate modified_row = ':'.join( [sample['Last name'], sample['First name'], sample['Telephone'], sample['Address'], sample['City'], sample['State'], sample['Birthdate']]) formatted_data.append(modified_row + '\n') except KeyError: # 捕获到KeyError时执行这里的逻辑 print(f"跳过无效数据:缺少Birthdate键,数据内容为{sample}") continue except ValueError: # 额外处理Birthdate格式错误的情况(比如不是用/分隔) print(f"跳过无效数据:Birthdate格式错误,数据内容为{sample}")
简单解释try-except的执行逻辑:
- 程序先执行
try块里的代码 - 如果代码抛出了
except后面指定的异常(比如这里的KeyError、ValueError),就会跳过try块里剩下的代码,直接执行对应except块的内容 - 如果没有异常,就完全跳过
except块,继续执行后续代码
完整修改后的代码
inputFile = 'raw.data.py' data = list() columns = ['First name','Last name','Telephone','Address','City','State','Birthdate'] for line in open(inputFile): if line.startswith('#'): continue # 清理行首尾的特殊字符 cleaned_line = line.strip().strip("', ") row = cleaned_line.split(':') # 确保元素数量匹配才加入数据列表 if len(row) == len(columns): data.append(dict(zip(columns, row))) formatted_data = list() for sample in data: try: birthdate = sample['Birthdate'] mm,dd,yy = birthdate.split('/') # 处理两位年份(默认补19前缀,可根据需求调整) if len(yy)==2: yy = '19' + yy birthdate = '/'.join([mm,dd,yy]) sample['Birthdate'] = birthdate # 按新格式拼接行内容 modified_row = ':'.join( [sample['Last name'], sample['First name'], sample['Telephone'], sample['Address'], sample['City'], sample['State'], sample['Birthdate']]) formatted_data.append(modified_row + '\n') except KeyError as e: print(f"错误:缺少必要键 {e},跳过该行数据:{sample}") except ValueError: print(f"错误:Birthdate格式无效,跳过该行数据:{sample}") with open('fixed.data','w') as f: f.writelines(formatted_data)
这段代码既修复了KeyError的核心问题,又增加了对无效数据的容错处理,能应对更多意外情况。
内容的提问来源于stack exchange,提问作者SB2000

