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
相关产品推荐
相关产品推荐

