Python在Try/Except循环中触发KeyError问题排查
问题分析:KeyError未被捕获导致Flask应用崩溃
问题场景
运行以下代码时,当接口响应的JSON不包含code键,系统会抛出key not found 'code'的错误,且部署在Heroku上的Flask应用直接崩溃,没有进入except TypeError代码块。
def create_hec_kw(self, kw): print(f'Creating Keyword {kw}') data = {'name': kw, 'slug': kw.lower().replace(' ', '-')} response = requests.post(self.create_url('tags'), headers=self.get_headers(), json=data) # created_kw_id = response.json()['data']['term_id'] if response.json()['code'] else response.json()['id'] print(f'The keyword response is {response.json()}') try: if response.json()['code']: created_kw_id = response.json()['data']['term_id'] else: created_kw_id = response.json()['id'] print(f'The id is {created_kw_id}') return created_kw_id except TypeError: created_kw_id = '' return created_kw_id
原因解析
- 异常类型不匹配:当访问字典中不存在的键时,Python抛出的是
KeyError,但你的except块只指定了捕获TypeError,这个异常不在捕获范围内,所以会直接向上传播,最终导致Flask应用崩溃。 - 重复解析响应:代码中多次调用
response.json(),会重复解析响应体,虽然不会直接导致崩溃,但属于不必要的性能损耗,建议先将解析结果存入变量复用。
修复方案
方案1:扩展捕获的异常类型
将KeyError加入except块,确保能捕获到键不存在的情况:
def create_hec_kw(self, kw): print(f'Creating Keyword {kw}') data = {'name': kw, 'slug': kw.lower().replace(' ', '-')} response = requests.post(self.create_url('tags'), headers=self.get_headers(), json=data) response_json = response.json() # 提前解析并存入变量 print(f'The keyword response is {response_json}') try: if response_json['code']: created_kw_id = response_json['data']['term_id'] else: created_kw_id = response_json['id'] print(f'The id is {created_kw_id}') return created_kw_id except (TypeError, KeyError): # 同时捕获两种异常 created_kw_id = '' return created_kw_id
方案2:使用字典get()方法避免异常
更稳妥的方式是用dict.get()方法访问键,不存在时返回None或指定默认值,从根源避免KeyError:
def create_hec_kw(self, kw): print(f'Creating Keyword {kw}') data = {'name': kw, 'slug': kw.lower().replace(' ', '-')} response = requests.post(self.create_url('tags'), headers=self.get_headers(), json=data) response_json = response.json() print(f'The keyword response is {response_json}') code = response_json.get('code') if code is not None: created_kw_id = response_json.get('data', {}).get('term_id', '') else: created_kw_id = response_json.get('id', '') if created_kw_id: print(f'The id is {created_kw_id}') return created_kw_id
内容的提问来源于stack exchange,提问作者user3324136
相关产品推荐
相关产品推荐

