报错“file is not a zip file”主因是用openpyxl引擎读取非.xlsx文件(如.xls、加密文件或旧版格式);应确认真实格式,.xls改用xlrd引擎(≤1.2.0),加密文件需预解密,显式指定engine='openpyxl'可避免自动猜测错误。

读Excel时pd.read_excel()报错“File is not a zip file”
这是用pandas打开非.xlsx格式(比如.xls、加密文件、或被另存为“Excel 97-2003 工作簿”的旧版文件)时最常遇到的报错。新版openpyxl默认只支持.xlsx,不处理.xls或加密文件。
- 先确认文件真实格式:
file your_file.xlsx(Linux/macOS)或看属性里的“文件类型”,别只信后缀名 - 如果是.xls,改用
engine='xlrd'(注意:xlrd ≥ 2.0.0已不支持.xlsx,所以得降级到1.2.0;更推荐统一转成.xlsx) - 如果文件被密码保护,pandas原生不支持解密,得先用
pywin32(Windows)或msoffcrypto-tool预处理 - 用
pd.read_excel('data.xlsx', engine='openpyxl')显式指定引擎,避免依赖pandas自动猜测
写入多个sheet时ExcelWriter覆盖已有sheet或报错“Permission denied”
常见于反复运行脚本时没关闭writer对象,或者在Excel程序里还开着目标文件。
- 必须用
with pd.ExcelWriter(...)上下文管理器,否则.close()容易漏掉,导致文件句柄未释放 - 想追加sheet而不是覆盖整个文件?
openpyxl支持,但得手动加载已有工作簿:ExcelWriter(..., engine='openpyxl', mode='a', if_sheet_exists='replace') -
if_sheet_exists可选'replace'、'overlay'或'error',别用默认值(会报错) - 写入后立刻用
os.path.getsize()检查文件大小是否非零,防止静默失败
日期列读进来变成数字(如44562)或NaT
pandas读Excel时,对Excel日期的解析依赖底层引擎和单元格格式。数字44562其实是Excel自1900-01-01起的天数,不是bug,是它的存储逻辑。
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
- 优先让Excel源文件把日期列设为“短日期”格式,再读 —— 这比后期转换更可靠
- 读取时加参数:
parse_dates=['date_col'],或用dtype={'date_col': 'datetime64[ns]'}强制类型 - 如果已读成整数,用
pd.to_datetime(df['col'], unit='d', origin='1899-12-30')转换(注意origin不是1900-01-01,因为Excel有闰年计算错误) - 写回Excel前,用
df['date_col'].dt.strftime('%Y-%m-%d')转字符串可避免格式错乱,但会丢失日期类型
清洗空值和合并单元格时fillna()和ffill()行为反直觉
Excel里合并单元格本质是“只在左上角存值,其余为空”,pandas读进来就是NaN,但直接fillna(method='ffill')可能跨行填充,破坏业务逻辑。
- 先用
df.isna().sum()确认空值分布,别假设“只有最后一列有空” - 按业务分组填充更安全:比如按
'category'列分组后,在每组内ffill(),避免A类数据污染B类 - 合并单元格对应的多行,往往需要
bfill()配合ffill()做两次,或用df.groupby(df['key'].notna().cumsum())构造伪组 - 清洗后务必检查
df.duplicated(subset=['id']).sum(),合并单元格误填充常导致重复ID
Excel的“视觉合并”和pandas的“结构化数据”之间没有自动映射关系,所有清洗动作都得基于你清楚哪几行实际属于同一逻辑记录 —— 这个判断没法靠代码猜出来。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










