Pandas调用xlrd读取XLS文件报错、单独用xlrd可正常打开问题求助
报错原因
- 非标准XLS文件校验不通过:部分第三方系统导出的XLS文件头不符合微软官方格式规范,xlrd本身做了兼容处理可以正常解析,但Pandas调用xlrd引擎前会执行自有的文件格式前置校验,这类非标准文件无法通过校验就会抛出对应错误。
- 字节流指针偏移:如果从S3拉取的
contents是BytesIO类文件对象,经过中间读取操作后指针可能已经移动到内容末尾,Pandas读取时无法读到有效文件头就会判定为非合法Excel文件;调用xlrd时使用的file_contents参数直接接收完整二进制内容,不受指针偏移影响。 - 版本适配bug:若使用Pandas≤1.2版本搭配xlrd≥2.0版本,部分小版本存在参数传递异常,Pandas会错误将二进制内容按文件路径处理,导致xlrd无法接收到正确的文件内容。
解决方案
方案1:将xlrd读取的工作表转为Pandas DataFrame(最稳定,适配所有xlrd可识别的文件)
直接复用已调通的xlrd读取逻辑,手动将工作表内容转换为DataFrame,完全跳过Pandas的前置校验步骤:
import pandas as pd import xlrd # 沿用已有的xlrd读取逻辑 book = xlrd.open_workbook(file_contents=contents) # 按需选择工作表,此处默认取第一个表,也可通过sheet_by_name("表名")指定 sheet = book.sheet_by_index(0) # 跳过前5行,从第6行开始读取所有行数据 data = [sheet.row_values(row_idx) for row_idx in range(5, sheet.nrows)] # 传入自定义列名生成DataFrame df = pd.DataFrame(data, columns=['some', 'column', 'headers'])
方案2:修复Pandas直接读取逻辑(适合不想改动原有代码结构的场景)
如果要继续使用pd.read_excel方法,可先重置字节流指针再调用:
from io import BytesIO # 若contents是BytesIO对象,先将指针重置到内容开头 if isinstance(contents, BytesIO): contents.seek(0) # 再执行原有的读取逻辑 df = pd.read_excel(contents, engine='xlrd', skiprows=5, names=['some', 'column', 'headers'])
如果是版本适配问题,可固定依赖版本解决:xlrd==1.2.0 + pandas>=1.3.0。
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

