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

Python解压脚本报错BadZipFile:文件不是压缩文件求助

解决Python批量解压子压缩文件夹时的BadZipFile错误

你遇到的这个BadZipFile: File is not a zip file错误,大概率是因为代码尝试把非压缩文件/文件夹当成zip包来打开了。根据你的描述,data_dir是普通文件夹,里面包含多个压缩子文件夹(应该是带.zip后缀的压缩包文件),但os.listdir(data_dir)会列出目录下所有内容——如果里面混有非zip格式的文件、普通文件夹,或者某个zip包损坏,就会触发这个错误。

先看你遇到的具体错误信息:

Error raise BadZipFile("File is not a zip file") BadZipFile: File is not a zip file

你的源目录路径:

  • data_dir = r'L:\DataQA\Python Unzip Files\Source Zipped'

问题分析

你的代码逻辑是遍历data_dir下的所有条目,直接用zipfile.ZipFile打开每个条目。但如果目录里存在非zip格式的内容,或者某个zip包损坏,就会抛出错误。而你提到把所有子文件夹打包成单个压缩包时代码能正常运行,说明单个完整zip包是没问题的,问题出在批量处理时的过滤和校验环节。

解决办法

我给你调整了代码,主要做了这几个优化:

  • 过滤zip文件:只处理.zip后缀的文件,跳过其他格式条目
  • 增强错误捕获:在打开zip包时捕获BadZipFile等异常,跳过无效文件并记录日志
  • 校验文件存在性:复制XML文件前检查文件是否存在,避免报错
  • 安全清理临时目录:使用shutil.rmtree时添加ignore_errors=True,避免目录不存在报错

修改后的代码如下:

import os
import zipfile
import shutil
import json
import logging
import time

def my_start_time():
    global start_time, cumulative_time, start_time_stamp
    start_time = time.time()
    this_time = time.localtime(start_time)
    start_time_stamp = '{:4d}{:02d}{:02d} {:02d}:{:02d}:{:02d}'.format(
        this_time.tm_year, this_time.tm_mon, this_time.tm_mday,
        this_time.tm_hour, this_time.tm_min, this_time.tm_sec)
    cumulative_time = start_time - start_time
    logging.info('Initial Setup: {:s}'.format(start_time_stamp))

def my_time():
    global cumulative_time
    time_taken = time.time() - start_time
    incremental_time = time_taken - cumulative_time
    cumulative_time = time_taken
    logging.info("Started: %s Complete: Cumulative: %.4f s Incremental: %.4f s\n" 
        % (start_time_stamp, cumulative_time, incremental_time) )

# 配置日志,增加时间戳便于排查问题
logging.basicConfig(filename='myunzip_task_log.txt', level=logging.DEBUG,
                    format='%(asctime)s - %(levelname)s - %(message)s')
my_start_time()
logging.info('Initial Setup...')

def write_to_json(data, file):
    try:
        with open(file, 'w') as f:
            json.dump(json.dumps(data, sort_keys=True), f)
        return True
    except Exception as e:
        logging.error(f"Failed to write to JSON file {file}: {str(e)}")
        return False

# 目录配置
data_dir = r'L:\DataQA\Python Unzip Files\Source Zipped'
temp_dir = r'L:\DataQA\Python Unzip Files\temp1'
new_dir = r'L:\DataQA\Python Unzip Files\temp2'
final_dir = r'L:\DataQA\Python Unzip Files\Destination Unzipped files'

# 提前创建必要的目录,避免后续报错
for dir_path in [temp_dir, new_dir, final_dir]:
    if not os.path.exists(dir_path):
        os.makedirs(dir_path)

# 过滤出data_dir下的有效zip文件,排除子目录和非zip文件
big_list = [item for item in os.listdir(data_dir) 
            if item.lower().endswith('.zip') 
            and os.path.isfile(os.path.join(data_dir, item))]

archive_count = len(big_list)
file_count = 152865
basename1 = os.path.join(final_dir,'GENERIC_ROUGHDRAFT')
basename2 = os.path.join(final_dir,'XACTDOC')

my_time()
logging.info('Unzipping {} valid zip archives...'.format(archive_count))

for folder in big_list:
    prior_count = file_count
    zip_path = os.path.join(data_dir, folder)
    logging.info('Starting to process: {}'.format(folder))
    
    # 安全清理临时目录,忽略不存在的情况
    shutil.rmtree(temp_dir, ignore_errors=True)
    os.mkdir(temp_dir)
    
    try:
        # 打开并解压第一层zip包
        with zipfile.ZipFile(zip_path, mode='r') as a_zip:
            a_zip.extractall(path=temp_dir)
        logging.info('Successfully unzipped: {}'.format(folder))
    except zipfile.BadZipFile:
        logging.error(f'Skipping invalid zip file: {folder} - File is not a valid zip')
        continue
    except Exception as e:
        logging.error(f'Error unzipping {folder}: {str(e)}')
        continue
    
    archive_count += 1
    logging.info('Cumulative total of {} archive(s) unzipped'.format(archive_count))
    
    # 处理临时目录下的内容
    bigger_list = os.listdir(temp_dir)
    logging.info('Current archive contains {} subfolders/files'.format(len(bigger_list)))
    
    for sub_folder in bigger_list:
        sub_item_path = os.path.join(temp_dir, sub_folder)
        # 检查当前条目是否是有效zip文件
        if not (sub_item_path.lower().endswith('.zip') and os.path.isfile(sub_item_path)):
            logging.warning(f'Skipping non-zip item: {sub_folder}')
            continue
        
        try:
            # 解压第二层zip包
            with zipfile.ZipFile(sub_item_path, mode='r') as b_zip:
                b_zip.extractall(path=new_dir)
        except zipfile.BadZipFile:
            logging.error(f'Skipping invalid sub zip file: {sub_folder}')
            continue
        except Exception as e:
            logging.error(f'Error unzipping sub file {sub_folder}: {str(e)}')
            continue
        
        # 检查需要复制的XML文件是否存在
        source_xml1 = os.path.join(new_dir, 'GENERIC_ROUGHDRAFT.xml')
        source_xml2 = os.path.join(new_dir, 'XACTDOC.xml')
        
        if not os.path.exists(source_xml1) or not os.path.exists(source_xml2):
            logging.error(f'Missing required XML files in {sub_folder}, skipping')
            continue
        
        # 复制并重命名文件
        file1 = "%s (%d).%s" % (basename1, file_count, 'xml')
        file2 = "%s (%d).%s" % (basename2, file_count, 'xml')
        shutil.copy(source_xml1, file1)
        shutil.copy(source_xml2, file2)
        file_count += 1
        
        # 清理new_dir,避免下一次解压的文件冲突
        shutil.rmtree(new_dir, ignore_errors=True)
        os.mkdir(new_dir)
    
    logging.info('{} subfolders processed successfully'.format(file_count - prior_count))

# 注意:删除源目录是高危操作,暂时注释,确认不需要源文件后再启用
# shutil.rmtree(data_dir)
# os.mkdir(data_dir)

my_time()
logging.info('Total of {0} files -- {1} pairs -- should be in {2}'.format(2*(file_count-152865), file_count-152865, final_dir))
time.sleep(1)
my_time()

额外说明

  • 我注释掉了删除源目录的代码shutil.rmtree(data_dir),这是非常危险的操作,建议你确认完全不需要源文件后再启用
  • 新增了目录预创建逻辑,避免因为临时目录不存在报错
  • 每一层解压都添加了错误捕获,确保单个无效文件不会导致整个脚本崩溃
  • 增加了XML文件存在性检查,避免复制不存在的文件报错

[文件资源管理器截图:Source Zipped目录下包含多个压缩文件夹]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:25:53