Python解析BacMet表格触发IndexError: list index out of range求助
错误定位
报错IndexError: list index out of range的触发原因非常明确:
- 无法正常运行的输入文件存在格式不规范问题:同一条基因记录的内容被意外的换行符拆成了两个物理行,拆分后第一个物理行经过制表符分割仅得到6个元素,列表最大索引为5,脚本硬取索引位置6的Compounds字段时直接越界。
- 原脚本没有对拆分后的字段长度做合法性校验,固定按标准格式取列位置,完全不兼容这类格式不规范的输入。
- 原脚本中
elif len(line) == 0: break是完全无效的冗余逻辑:逐行读取文件时,未到达文件末尾的每一行长度至少为1(换行符),这个判断永远不会触发,没有实际作用。
修复内容
- 增加字段长度校验机制:拆分后字段数不足时,自动缓存当前行内容,拼接后续续行的片段,直到组成完整记录后再解析,避免越界
- 移除冗余无效判断
- 替换原脚本中依赖numpy的去重逻辑,改用Python原生set实现,减少不必要的第三方依赖
- 增加Compounds字段的空值兜底判断,避免字段为空时触发正则匹配报错
- 清理原脚本中残留的无意义代码片段
enter code here
修复后完整脚本
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys import os import re from collections import OrderedDict def main(): if len(sys.argv) < 2: print("usage: python3 {} <bacmat_out_table> > output".format(sys.argv[0])) sys.exit(1) bacmat_out = os.path.abspath(sys.argv[1]) class_sum = OrderedDict() # 缓存上一条不完整的记录片段,用于拼接跨行内容 pending_line = "" with open(bacmat_out) as fh: for line in fh: # 跳过空行、表头行 if re.search(r"^\s*$|^Query", line): continue # 拼接待处理的行内容 full_line = pending_line + line pending_line = "" fields = full_line.strip().split("\t") # 字段数不足时,暂存当前行等待拼接后续内容 if len(fields) <= 6: pending_line = full_line continue # 提取Compounds列并做空值校验 compounds = fields[6] if not compounds.strip(): continue if re.search(r'\[.*\]', compounds): compounds_class = re.findall(r'\[class:\s?(.+?)\]', compounds) # 原生set去重 compounds_class = list(set(compounds_class)) if len(compounds_class) > 0: for i in compounds_class: class_sum.setdefault(i, 0) class_sum[i] += 1 else: compounds = compounds.strip('"').strip("'").strip() if not compounds: continue class_sum.setdefault(compounds, 0) class_sum[compounds] += 1 print("Class\tCount") for key in sorted(class_sum.keys()): print(key, class_sum[key], sep="\t") if __name__ == '__main__': main()
运行效果
- 可自动识别输入文件中被意外换行拆分的不完整记录,拼接后正常解析
- 遇到格式不规范的短行不会直接崩溃,会自动缓存等待后续拼接
- 去掉了不必要的numpy依赖,降低运行环境配置成本
- 兼容Compounds字段为空、带引号包裹等边界场景
内容的提问来源于stack exchange,提问作者Budheswar
相关产品推荐
相关产品推荐

