You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python如何读取ZIP压缩包内受密码保护的.xlsx文件

适配要求的实现方案

针对你遇到的两个核心约束——win32com必须传入物理文件路径无法直接接收BytesIO、不能全量解压整个ZIP包,可采用单条目临时中转方案落地,全程无需解压整个压缩包,仅针对单个待处理的Excel条目做最小化临时文件操作,处理完成即刻清理,完全复用你已有的两套读取逻辑。

核心实现逻辑

  • 遍历ZIP条目时,保留原有带ZIP密码读取字节流的逻辑,不触发全量解压,仅按需读取当前匹配到的单个Excel条目字节
  • 针对当前读取到的单个Excel字节流,通过系统标准临时目录生成独立临时文件,拿到可被win32com识别的绝对路径
  • 复用原有win32com解密Excel、另存为无密码副本的逻辑,完成密码校验和文件解密
  • 拿到pandas读取的DataFrame后,在finally块中强制清理所有临时文件、退出Excel COM进程,不留磁盘残留

关键实现注意点

  • 临时文件必须使用Python标准库tempfile模块生成,不要手动在业务目录拼接临时文件名,避免多进程冲突、文件被占用的问题
  • win32com实例要设置Visible = False、DisplayAlerts = False,避免弹出Excel窗口、弹出密码确认弹窗打断流程
  • 需严格区分两层密码层级:ZIP压缩包的条目加密密码用于从ZIP内读出Excel原始字节,Excel文件本身的打开密码用于win32com解密Excel内容,两层校验独立,不能混用
  • 所有文件清理操作必须放在try-finally块中,即使读取过程中抛出异常,也要确保临时文件不残留、Excel进程不挂在后台
  • 相比引入第三方Excel解密库再传给pandas的方案,这个方案完全复用你已上线的win32解密逻辑,对xls、xlsx两种格式的兼容性和现有环境完全一致,不需要做额外的依赖适配

核心参考代码

import os
import zipfile
import tempfile
import win32com.client
import pandas as pd

# 原有业务参数
base_folder = "业务根目录"
zip_filename = "目标压缩包文件名.zip"
zip_entry_pwd = bytes("ZIP条目解压密码", "utf-8")
excel_open_pwd = "受保护Excel的打开密码"

result = {}
with zipfile.ZipFile(os.path.join(base_folder, zip_filename)) as z:
    for file in z.namelist():
        # 跳过ZIP内的目录条目
        if os.path.isdir(file):
            continue
        if not (file.endswith('.xlsx') or file.endswith('.xls')):
            continue
        # 带ZIP密码读取当前Excel条目的字节,不触发全量解压
        excel_raw_bytes = z.read(file, pwd=zip_entry_pwd)
        # 生成独立临时Excel文件
        with tempfile.NamedTemporaryFile(suffix='.xlsx', delete=False) as tmp_file:
            tmp_excel_path = tmp_file.name
            tmp_file.write(excel_raw_bytes)
        tmp_unprotect_path = tmp_excel_path.replace('.xlsx', '_unprot.xlsx')
        xlApp = None
        try:
            # 初始化COM组件,解密Excel
            xlApp = win32com.client.Dispatch("Excel.Application")
            xlApp.Visible = False
            xlApp.DisplayAlerts = False
            wb = xlApp.Workbooks.Open(tmp_excel_path, 0, True, None, excel_open_pwd)
            wb.SaveAs(tmp_unprotect_path, None, '', '')
            wb.Close(False)
            # pandas读取无密码副本
            result[file] = pd.read_excel(tmp_unprotect_path, sheet_name=None)
        finally:
            # 强制清理资源
            if xlApp:
                xlApp.Quit()
            for tmp_path in [tmp_excel_path, tmp_unprotect_path]:
                if os.path.exists(tmp_path):
                    os.remove(tmp_path)

内容的提问来源于stack exchange,提问作者Tom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.26 03:54:03