应停用xlrd 2.0+,改用openpyxl读.xlsx或降级xlrd==1.2.0;校验文件头(.xlsx为PK\x03\x04,.xls为D0\xCF\x11\xE0),并启用openpyxl的read_only=True和data_only=True模式规避解析错误。

遇到 xlrd.biffh.XLRDError: Unsupported format, or corrupt file 怎么办
这通常不是 Excel 文件真损坏,而是 xlrd 库在 2.0+ 版本后彻底弃用了对 .xlsx 的支持——它只认老式 .xls,且对加密、宏、损坏流控极敏感。直接换库是最省事的解法。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 如果文件确定是
.xlsx或.xlsb,立刻停用xlrd,改用openpyxl(纯 Python,支持.xlsx)或pyxlsb(专解.xlsb) - 若必须用
xlrd,确认文件是真实.xls(不是重命名的.xlsx),并降级到xlrd==1.2.0(最后支持.xlsx的版本) - 用
file命令或十六进制头校验:正常.xlsx是PK\x03\x04,.xls是D0\xCF\x11\xE0;头不对就别硬读
用 openpyxl 加载时抛 InvalidFileException 或卡死
openpyxl 对循环引用(如公式 A1 引用 B1,B1 又引用 A1)和结构错乱(如共享字符串表缺失、sheet 关系断裂)默认不宽容,会直接中断。但你可以让它“尽力而为”。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 启用
read_only=True模式:跳过解析样式、公式、合并单元格等易出错环节,大幅降低崩溃概率 - 加
data_only=True:把公式结果当值读,绕过公式引擎对循环引用的校验 - 捕获异常后,尝试用
zipfile.ZipFile手动解压.xlsx,检查xl/workbook.xml是否可读、xl/sharedStrings.xml是否为空或截断 - 对已知有公式的文件,提前用 Excel 手动“另存为”一次,能修复多数结构松动问题
如何检测并跳过损坏的 sheet 而不中断整个读取
openpyxl.load_workbook() 默认加载全部 sheet,一个 sheet 坏掉整调用就崩。得手动控制加载粒度。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 先用
openpyxl.load_workbook(filename, read_only=True, keep_vba=False)获取 workbook 对象,此时不真正加载数据 - 遍历
wb.sheetnames,对每个 sheet 名调用wb.get_sheet_by_name(name),再用try/except包裹sheet.iter_rows()的首次迭代 - 若某 sheet 报
KeyError(缺 sharedStrings)、AttributeError(sheet 对象不完整),记录日志后continue,不影响其余 sheet - 注意:
read_only=True下不能用sheet['A1'].value这种索引方式,必须用iter_rows()或iter_cols()
用 pandas.read_excel() 时 silent fail 或读空表
pandas 底层调用引擎(openpyxl / xlrd / calamine)不同,行为差异大。silent fail 多因引擎自动降级或跳过异常 sheet 后没报错。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 显式指定
engine:比如pd.read_excel('x.xlsx', engine='openpyxl'),避免 pandas 自行选错引擎 - 加
keep_default_na=False和na_values=None,防止空单元格被误判为NaN导致整行丢弃 - 用
sheet_name=None让 pandas 返回 dict of DataFrames,再逐个检查df.shape[0] > 0,定位是哪个 sheet 空了 - 若怀疑是编码或 BOM 问题(尤其 Windows 生成的 CSV 导出再转 Excel),先用
chardet查原始字节编码,再用openpyxl的guess_type辅助判断
循环引用本身不会让 Excel 文件打不开,但会让 Python 解析器在构建依赖图时陷入无限递归或栈溢出。真正棘手的是那些“看起来能打开,但 XML 结构残缺”的文件——它们往往需要人工干预或 Excel 重救,自动化处理总有边界。


















