Python try块内异常未触发except分支,请求排查原因
问题描述
我正在处理欧盟议会投票结果的XML文件,发现投票结果的描述存在两种格式:纯文本形式和URL形式。其中PV-9-2022-09-12-RCV_FR.xml文件处理失败,PV-9-2022-07-06-RCV_FR.xml可正常运行。
我已添加try-except语句,但代码抛出string indices must be integers异常时,并未进入except分支处理,直接退出。需排查异常未被正确捕获的原因。
相关代码
for currentfile in f: mytree = ET.parse(xmlfiles + "\\" + currentfile) myroot = mytree.getroot() dixml = etree_to_dict(myroot) for votes in dixml['PV.RollCallVoteResults']['RollCallVote.Result']: try: title = votes['RollCallVote.Description.Text'] # 此处触发异常 titletype = type(title) if titletype == dict: title=title['#text'] except : title = votes['RollCallVote.Description.Text']['a']['#text'] try: ltitle = title.lower() except : print(type(title)) if stringtosearch in ltitle: print(title,currentfile)
报错栈信息
Message=string indices must be integers Source=...debug.py StackTrace: File "...debug.py", line 44, in <module> title = votes['RollCallVote.Description.Text'] During handling of the above exception, another exception occurred: File "...debug.py", line 44, in <module> title = votes['RollCallVote.Description.Text'] File "...debug.py", line 49, in <module> (Current frame) title = votes['RollCallVote.Description.Text']['a']['#text']
问题排查与解决
核心原因分析
- 循环对象类型不统一:
dixml['PV.RollCallVoteResults']['RollCallVote.Result']在出错的XML中是单个字典,而非列表。此时for votes in ...会遍历字典的键(字符串类型),而非预期的投票项字典。执行votes['RollCallVote.Description.Text']时,相当于对字符串使用字符串索引,直接抛出string indices must be integers异常。 - except分支未做防护:即使第一个异常被捕获,
except分支内的代码votes['RollCallVote.Description.Text']['a']['#text']同样会因为votes是字符串而抛出相同异常,且该代码未被包裹在try块中,导致程序直接退出。 - 裸except风险:使用
except :会捕获所有异常,但此处的异常发生在except分支内部,无法被当前try-except捕获。
修复步骤
1. 统一循环对象为列表
先判断RollCallVote.Result的类型,若为单个字典则转为列表,避免遍历字典键:
roll_call_results = dixml['PV.RollCallVoteResults']['RollCallVote.Result'] # 处理单个投票结果的情况 if not isinstance(roll_call_results, list): roll_call_results = [roll_call_results] for votes in roll_call_results: # 后续逻辑
2. 细化异常处理与数据结构检查
明确捕获特定异常,同时在处理RollCallVote.Description.Text时先检查类型,避免索引错误:
try: desc_text = votes['RollCallVote.Description.Text'] if isinstance(desc_text, dict): # 优先处理带URL的格式 title = desc_text['a']['#text'] if 'a' in desc_text else desc_text['#text'] else: # 纯文本格式直接赋值 title = desc_text except (KeyError, TypeError) as e: print(f"投票项解析失败: {e},文件: {currentfile}") continue # 跳过当前异常项,继续处理下一个
3. 确保标题为字符串类型
在调用lower()前检查类型,避免后续报错:
if not isinstance(title, str): print(f"标题类型异常,文件: {currentfile},类型: {type(title)}") continue ltitle = title.lower() if stringtosearch in ltitle: print(title, currentfile)
修复后完整代码示例
for currentfile in f: mytree = ET.parse(xmlfiles + "\\" + currentfile) myroot = mytree.getroot() dixml = etree_to_dict(myroot) # 统一投票结果为列表格式 roll_call_results = dixml['PV.RollCallVoteResults']['RollCallVote.Result'] if not isinstance(roll_call_results, list): roll_call_results = [roll_call_results] for votes in roll_call_results: title = "" try: desc_text = votes['RollCallVote.Description.Text'] if isinstance(desc_text, dict): title = desc_text['a']['#text'] if 'a' in desc_text else desc_text['#text'] else: title = desc_text except (KeyError, TypeError) as e: print(f"解析投票项出错: {e},文件: {currentfile}") continue # 确保标题是字符串后再处理 if not isinstance(title, str): print(f"标题类型异常: {type(title)},文件: {currentfile}") continue ltitle = title.lower() if stringtosearch in ltitle: print(title, currentfile)
内容的提问来源于stack exchange,提问作者vilmarci
相关产品推荐
相关产品推荐

