Python使用shutil.unpack_archive无法解压临时zip文件问题排查
报错根因
两个问题共同导致该报错:
- Windows系统默认对打开状态的文件施加独占锁,你通过路径
source_zip.name调用shutil.unpack_archive时,shutil会尝试重新打开该文件,此时原文件句柄还未关闭,在Windows环境下会出现读取异常;同时下载方法写入文件后,内容暂存在内存缓冲区未同步到磁盘,磁盘上的临时zip文件内容为空/不完整,自然无法被识别为有效zip包。 - 代码存在拼写错误:存储桶参数
my_buicket为错误拼写,正确应为my_bucket,该问题不会触发当前解压报错,但会导致后续下载阶段请求失败。
解决方案
二选一即可:
方案1:兼容所有Python版本(推荐)
创建临时文件时关闭自动删除,下载完成后先强制将缓冲区内容刷入磁盘,关闭文件句柄后再执行解压,最后手动清理临时文件,彻底规避Windows文件锁问题:
import shutil import tempfile import os with tempfile.NamedTemporaryFile(suffix=".zip", delete=False) as source_zip: temp_zip_path = source_zip.name # 修正拼写后的存储桶参数 aws_util.download(my_bucket, "my_folder/design.zip", source_zip) # 强制将内存缓冲区的内容写入磁盘,保证文件完整 source_zip.flush() os.fsync(source_zip.fileno()) try: shutil.unpack_archive(temp_zip_path, "myfile", "zip") finally: # 手动删除临时文件,避免残留 os.unlink(temp_zip_path)
方案2:简化写法(Python 3.7+可用)
高版本Python的shutil.unpack_archive支持直接传入类文件对象,不需要通过路径二次打开文件,也就不会触发文件锁冲突,代码更简洁:
import shutil import tempfile with tempfile.NamedTemporaryFile(suffix=".zip") as source_zip: aws_util.download(my_bucket, "my_folder/design.zip", source_zip) # 刷新缓冲区、将文件指针重置到文件开头 source_zip.flush() source_zip.seek(0) # 直接传入文件对象解压 shutil.unpack_archive(source_zip, "myfile", "zip")
排查补充
如果按上述修改后仍报相同错误,先检查下载的文件是否完整:在下载完成后打印文件大小,如果大小为0或和预期zip体积差距极大,说明是aws_util.download本身的写入逻辑存在问题,和临时文件机制无关。
内容的提问来源于stack exchange,提问作者zsh_18
相关产品推荐
相关产品推荐

