Python提取以“~$”开头的文件时崩溃,求解决方案
问题分析
你遇到的问题大概率是因为以~$开头的文件是Windows系统生成的临时锁定文件(比如Office文档编辑时的缓存文件),这类文件在被打包时可能处于未完全写入的状态,导致zip条目存在隐性损坏——Windows资源管理器会自动忽略这类临时文件的异常,而Python的zipfile模块对zip结构的校验更严格,因此触发BadZipFile错误。手动重新打包时,临时文件已经被释放,所以能正常解析。
解决方案
一、用原生zipfile模块优化处理
1. 提前跳过临时文件
既然~$开头的文件都是临时缓存,完全可以直接跳过这类文件,避免触发错误:
import zipfile import os with zipfile.ZipFile(file_name, 'r') as zip_ref: for file in zip_ref.namelist(): # 获取文件名(兼容Windows/Unix路径分隔符) file_name_only = os.path.basename(file) # 跳过~$开头的临时文件 if file_name_only.startswith('~$'): print(f'Skipping temp file: {file_name_only}') continue file_extension = os.path.splitext(file)[1] fullPath_to_extracted_file = os.path.join(tempZipPath, file) print(f'Zip member file: {file_name_only}') # 你的原有过滤逻辑(跳过无需处理的文件) # ... try: zip_ref.extract(file, tempZipPath) except Exception as e: print(f'Failed to extract {file}: {str(e)}') continue
2. 捕获异常并容错
如果必须处理这类文件,可以在提取时捕获异常,避免整个程序崩溃:
import zipfile import os with zipfile.ZipFile(file_name, 'r') as zip_ref: for file in zip_ref.namelist(): file_name_only = os.path.basename(file) print(f'Zip member file: {file_name_only}') # 你的原有过滤逻辑 # ... try: zip_ref.extract(file, tempZipPath) except zipfile.BadZipFile as e: print(f'Skipping corrupted file {file}: {e}') except Exception as e: print(f'Unexpected error extracting {file}: {e}')
3. 预检查zip完整性
用zip_ref.testzip()检测所有损坏的条目,提前过滤:
import zipfile with zipfile.ZipFile(file_name, 'r') as zip_ref: bad_files = zip_ref.testzip() if bad_files: print(f'Found corrupted files in zip: {bad_files}') for file in zip_ref.namelist(): if file == bad_files: continue # 后续处理逻辑
二、更健壮的替代库
如果需要更强的兼容性和容错性,可以使用以下第三方库:
1. patool
patool是跨平台的压缩文件处理库,支持几乎所有主流压缩格式,底层会自动调用合适的系统工具(如unzip命令),对损坏或异常的zip包容错性更强。
- 安装:
pip install patool - 使用示例:
import patoolib # 提取整个zip包到指定目录 patoolib.extract(file_name, outdir=tempZipPath) # 如需筛选文件,可先解压到临时目录再遍历处理
2. pyunpack
pyunpack基于patool封装,提供更简洁的API:
- 安装:
pip install pyunpack patool - 使用示例:
from pyunpack import Archive Archive(file_name).extractall(tempZipPath)
3. shutil.unpack_archive
Python标准库的shutil模块也提供了解压功能,自动调用合适的后端处理,对边缘情况的处理比原生zipfile更友好:
import shutil shutil.unpack_archive(file_name, tempZipPath, format='zip')
内容的提问来源于stack exchange,提问作者Brian at Work
相关产品推荐
相关产品推荐

