一、文件压缩与解压缩模块 zipfile简介
zipfile 是 python 标准库中用于处理 zip 压缩文件的模块,提供了创建、读取、写入、解压 zip 文件的完整功能。它支持多种压缩算法,无需安装额外依赖,是处理 zip 格式的首选工具。
核心功能与常用类
zipfile.zipfile 类
这是模块的核心类,用于创建和操作 zip 文件,常用参数:
file:zip 文件路径或文件对象mode:操作模式('r'读取、'w'创建、'a'追加)compression:压缩算法(zip_stored无压缩,zip_deflated常用压缩)
常用操作示例
1. 读取 zip 文件内容
import zipfile
with zipfile.zipfile('example.zip', 'r') as zf:
# 查看压缩包内所有文件
print(zf.namelist()) # 返回文件名列表
# 查看文件信息(大小、压缩率等)
for info in zf.infolist():
print(f"文件名: {info.filename}, 原始大小: {info.file_size}, 压缩后: {info.compress_size}")
2. 解压 zip 文件
import zipfile
with zipfile.zipfile('example.zip', 'r') as zf:
# 解压所有文件到指定目录(默认当前目录)
zf.extractall(path='解压目录')
# 解压单个文件
zf.extract('文件路径/文件名.txt', path='单个文件解压目录')
3. 创建 zip 文件(压缩文件/文件夹)
import zipfile
import os
# 压缩单个文件
with zipfile.zipfile('output.zip', 'w', zipfile.zip_deflated) as zf:
zf.write('file1.txt', arcname='file1.txt') # arcname 可指定压缩包内文件名
# 压缩文件夹(含子目录)
def zip_folder(folder_path, zip_path):
with zipfile.zipfile(zip_path, 'w', zipfile.zip_deflated) as zf:
for root, dirs, files in os.walk(folder_path):
for file in files:
file_path = os.path.join(root, file)
# 保持相对路径,确保文件夹结构
arcname = os.path.relpath(file_path, os.path.dirname(folder_path))
zf.write(file_path, arcname=arcname)
zip_folder('需要压缩的文件夹', 'result.zip')
4. 向现有 zip 追加文件
import zipfile
with zipfile.zipfile('existing.zip', 'a', zipfile.zip_deflated) as zf:
zf.write('new_file.txt') # 追加新文件到已有压缩包
注意事项
- 压缩算法:
zip_deflated需要系统支持 zlib 库(通常默认支持),否则需使用无压缩的zip_stored。 - 路径处理:压缩文件夹时需通过
arcname控制路径,避免生成冗余的绝对路径。 - 大型文件:处理大文件时建议使用
with语句,确保资源正确释放。
通过 zipfile 模块,可轻松实现 zip 文件的全流程管理,满足日常压缩/解压需求。
二、案例实操
2.0 测试文件准备
原始结构为:
dir_level_1/
├── file1.txt
├── subfolder1/
│ └── file2.txt
└── subfolder2/
└── subsubfolder/
└── file3.txt
程序设计初衷:
将目录“dir_level_1”下所有的文件、子文件夹、子文件夹下的文件,安装原先的层次结构,压缩为一个文件“dir_level_1.zip”。
2.1 综合案例:实现文件压缩、查看压缩内容、解压
"""
14-5 文件压缩与解压模块-zipfile
操作系统提供将一般文件或目录进行压缩的功能,压缩后的扩展名是zip,
python有 zipfile 模块也可以将文件或目录压缩以及解压缩。
压缩文件或目录:
zipfile.zipfile(file_name, mode='w', compression=zip_deflated)
file_name: 压缩文件的名称
mode: 压缩文件的模式,w表示写入,a表示追加
compression: 压缩算法,zip_deflated表示使用 deflate 算法进行压缩
解压文件或目录:
zipfile.zipfile(file_name, mode='r')
14-5-1 执行文件或目录的压缩
说明:
执行文件压缩前首先要使用zipfile()方法创建一个压缩后的文件对象,在
这个方法中另外要加上“w”参数,表明未来是提供 write() 方法写入文件。
语法:
filezip = zipfile.zipfile('out.zip', mode='w',compression=zip_deflated)
上述filezip和out.zip皆可以自由命名,filezip是压缩文件对象,代表的out.zip,
未来将被压缩的文件数据写入到此对象中,就可以将结果保存为 out.zip 文件了。
注意:
1、虽然zipfile()无法执行整个目录的压缩,不过可以使用循环(递归)方式将目录底下的文件或文件夹进行压缩,即可达到压缩整个目录的目的。
详见:c14-5.2_zip_with_hierarchy.py
14-5-2 读取zip文件
说明:
1、listzipinfo.namelist() : 返回zip文件中所有文件的名称列表(list)。
2、listzipinfo.infolist() : 返回各个元素的属性,如文件名、文件大小、压缩结果大小、文件时间、文件crc码等。
语法:
listzipinfo = zipfile.zipfile('dir_level_1.zip', 'r')
print(listzipinfo.namelist()) # 获取文件(夹)列表
print('\n')
for fileinfo in listzipinfo.infolist():
print(fileinfo.filename,'\t', fileinfo.file_size,'\t', fileinfo.compress_size)
14-5-3 解压缩zip文件
说明:
1、zipfile.extractall() : 解压缩zip文件。
2、zipfile.extract(filename) : 解压缩指定文件。
3、zipfile.extractall(path) : 解压缩zip文件到指定目录。
语法:
listzipinfo = zipfile.zipfile('dir_level_1.zip', 'r')
listzipinfo.extractall() # 解压所有文件
listzipinfo.extract('dir_level_1.zip') # 解压指定文件
listzipinfo.close()
"""
print("----------------------- 案例-14-5-1 执行文件或目录的压缩 -----------------------")
# ch14_41.py : 将当前工作目录下的 dir_level_1 目录压缩,压缩结果存储在 dir_level_1.zip 文件中.
"""
代码说明:
这行代码的作用是遍历dir_level_1目录下的所有文件和目录(但不包括子目录中的内容)。
具体解释如下:
glob.glob('dir_level_1/*'):
glob是一个用于匹配文件路径的模块,支持unix shell-style的通配符
dir_level_1/*表示匹配dir_level_1目录下的所有文件和目录(一级内容)
这个表达式会返回一个包含所有匹配路径的列表
for name in ...:
遍历glob返回的每个文件/目录路径
根据对项目文件结构的查看,dir_level_1目录包含以下内容:
- 多个文件:2.docx、out14_27.txt等
- 一个子目录:dir_level_2(包含1.docx和1.txt)
需要注意的是,dir_level_1/*这种模式只会匹配dir_level_1目录下的直接内容,不会递归匹配子目录中的文件。所以在示例中,它会匹配到2.docx、out14_27.txt等文件以及 dir_level_2目录本身,但不会匹配dir_level_2 目录中的1.docx和1.txt。
在代码中,这些匹配到的文件和目录会被逐一添加到dir_level_1.zip压缩文件中。
"""
import zipfile
import glob, os
filezip = zipfile.zipfile('dir_level_1.zip', 'w')
for name in glob.glob('dir_level_1/*'): # 遍历指定目录下的所有文件,但测试下来,仅会压缩dir_level_1下首层文件及文件夹,而不会将二层dir_level_1\dir_level_2下的文件(如1.txt,1.docx)压缩进dir_level_1.zip中
filezip.write(name, os.path.basename(name), zipfile.zip_deflated) # 参数3为压缩方式
filezip.close()
print("----------------------- 案例-14-5-2 读取zip文件 -----------------------")
# ch14_41.py :
import zipfile
listzipinfo = zipfile.zipfile('dir_level_1.zip', 'r')
print(listzipinfo.namelist()) # 获取文件(夹)列表
print('\n')
for fileinfo in listzipinfo.infolist():
print(fileinfo.filename,'\t', fileinfo.file_size,'\t', fileinfo.compress_size, '\t', fileinfo.date_time, '\t', fileinfo.crc)
'''
['2.docx', 'out14_27.txt', 'out14_28.txt', 'out14_29.txt', 'out14_30.txt', 'out14_31.txt', 'out41_v3.zip', 'dir_level_2/']
2.docx 10240 9080 (2025, 8, 3, 1, 4, 52) 1145032402
out14_27.txt 13 15 (2025, 8, 2, 18, 23, 8) 2445962250
out14_28.txt 3 5 (2025, 8, 2, 18, 23, 8) 595022058
out14_29.txt 47 34 (2025, 8, 2, 18, 23, 8) 1873662565
out14_30.txt 51 36 (2025, 8, 2, 18, 23, 8) 24013343
out14_31.txt 101 42 (2025, 8, 2, 18, 23, 8) 676495025
out41_v3.zip 97041 71141 (2025, 8, 3, 9, 40, 58) 2754552733
dir_level_2/ 0 0 (2025, 8, 3, 0, 59, 16) 0
'''
print("----------------------- 案例-14-5-3 解压缩zip文件 -----------------------")
# ch14_43.py : 将程序实例 ch14_41.py 所建立的 dir_level_1.zip 解压缩,同时将解压结果存入 out43 目录
import zipfile
fileunzip = zipfile.zipfile("dir_level_1.zip", "r")
fileunzip.extractall("out43")
fileunzip.close()
2.2 压缩方法优化-v1版本
上一版压缩方法的缺陷:
代码中:
filezip = zipfile.zipfile('dir_level_1.zip', 'w')
for name in glob.glob('dir_level_1/*'):
filezip.write(name, os.path.basename(name), zipfile.zip_deflated)
这里的filezip对象无法将文件夹下dir_level_1下文件夹dir_level_2中的文件1.docx压缩进来,而只会将dir_level_2文件夹本身压缩进来,未达到程序实现功能的初衷。
改进说明:
要解决级联压缩文件夹(包含子文件夹结构)的问题,需要递归遍历文件夹中的所有文件,并保持原有的目录结构。
代码解释
要解决级联压缩文件夹(包含子文件夹结构)的问题,需要递归遍历文件夹中的所有文件,并保持原有的目录结构。以下是实现这一功能的完整代码:
代码清单:
zip_recursive.py
import zipfile
import os
def zip_directory(folder_path, zip_file):
"""
递归压缩文件夹及其子目录中的所有文件
参数:
folder_path (str): 要压缩的文件夹路径
zip_file (zipfile.zipfile): 已打开的zipfile对象
"""
# 遍历文件夹中的所有内容
for item in os.listdir(folder_path):
item_path = os.path.join(folder_path, item)
# 如果是文件,直接添加到压缩包
if os.path.isfile(item_path):
# 计算相对路径,保持目录结构
arcname = os.path.relpath(item_path, os.path.dirname(folder_path))
zip_file.write(item_path, arcname=arcname)
print(f"已添加文件: {arcname}")
# 如果是文件夹,递归处理
elif os.path.isdir(item_path):
zip_directory(item_path, zip_file)
# 使用示例
if __name__ == "__main__":
# 要压缩的根文件夹路径
root_folder = "dir_level_1"
# 压缩文件保存路径
zip_path = "dir_level_1.zip"
# 创建并打开zip文件
with zipfile.zipfile(zip_path, 'w', zipfile.zip_deflated) as zipf:
zip_directory(root_folder, zipf)
print(f"压缩完成,文件保存为: {zip_path}")
代码解析:
核心函数:
zip_directory函数通过递归方式处理文件夹及其子文件夹- 对于文件:直接添加到压缩包,并通过
arcname参数保持相对路径 - 对于子文件夹:递归调用自身处理
- 对于文件:直接添加到压缩包,并通过
关键技术点:
- 使用
os.path.relpath计算文件相对路径,确保压缩包内保持原有的目录结构 - 使用
with语句管理 zipfile 对象,确保资源正确释放 - 使用
zip_deflated模式创建压缩的zip文件(而不是仅存储)
- 使用
使用方法:
- 将
root_folder设置为根文件夹路径(如 “dir_level_1”) - 运行程序后,会将 dir_level_1 下所有文件、子目录(包括 dir_level_2 中的 1.docx)完整压缩到 dir_level_1.zip 中
- 将
这样处理后,压缩包内会完整保留原有的文件夹层次结构,而不是仅压缩最内层的文件夹。
2.3 压缩方法优化-v2版本
v1版缺陷:
这样实现不能忠实的反馈原文件夹结构,本意是希望原先dir_level_1下的文件夹和文件都压缩至dir_level_1目录下,而目前的代码实现的逻辑是dir_level_1下的文件是放在了dir_level_1下,但dir_level_1下的文件夹,如 dir_level_2 却没有放在dir_level_1下,而是与dir_level_1平级了。
改进说明:
要解决文件夹结构忠实还原的问题,关键在于正确设置压缩包内的相对路径。以下是改进后的代码,确保所有文件和子文件夹都正确嵌套在根目录下。
核心改进点:
- 明确将根文件夹名称(
root_basename)作为压缩包内的顶级目录 - 所有文件和子文件夹都通过
os.path.join(root_basename, ...)构建路径,确保嵌套在根目录下 - 使用
zip_subdirectory专门处理子文件夹,保持完整的层级关系
- 明确将根文件夹名称(
结构保证:
假设原始结构为:dir_level_1/ ├── file1.txt ├── subfolder1/ │ └── file2.txt └── subfolder2/ └── subsubfolder/ └── file3.txt压缩后在zip文件中会保持完全相同的结构:
dir_level_1/ ├── file1.txt ├── subfolder1/ │ └── file2.txt └── subfolder2/ └── subsubfolder/ └── file3.txt使用方法:
- 将
root_folder设置为根目录(如 “dir_level_1”) - 运行程序后,所有内容都会被正确压缩到该根目录下,不会出现平级问题
- 将
这种实现方式能精确还原原始文件夹的层级结构,确保子文件夹都正确嵌套在指定的根目录下。
代码清单:
zip_with_hierarchy.py
import zipfile
import os
def zip_directory(root_folder, zip_file):
"""
递归压缩指定文件夹,保持完整的目录结构
参数:
root_folder (str): 要压缩的根文件夹路径
zip_file (zipfile.zipfile): 已打开的zipfile对象
"""
# 获取根文件夹的基本名称,作为压缩包内的顶级目录
root_basename = os.path.basename(root_folder)
# 遍历根文件夹中的所有内容
for item in os.listdir(root_folder):
item_path = os.path.join(root_folder, item)
# 构建压缩包内的相对路径,确保所有内容都在根文件夹名下
arcname = os.path.join(root_basename, item)
if os.path.isfile(item_path):
# 添加文件,使用构建的相对路径
zip_file.write(item_path, arcname=arcname)
print(f"已添加文件: {arcname}")
elif os.path.isdir(item_path):
# 递归处理子文件夹,同时保持目录结构
zip_subdirectory(item_path, zip_file, root_basename)
def zip_subdirectory(subfolder_path, zip_file, root_basename):
"""递归处理子文件夹,保持相对路径结构"""
# 获取当前子文件夹相对于根文件夹的路径
rel_path = os.path.relpath(subfolder_path, os.path.dirname(subfolder_path))
# 构建压缩包内的完整路径
base_arcname = os.path.join(root_basename, rel_path)
for item in os.listdir(subfolder_path):
item_path = os.path.join(subfolder_path, item)
arcname = os.path.join(base_arcname, item)
if os.path.isfile(item_path):
zip_file.write(item_path, arcname=arcname)
print(f"已添加文件: {arcname}")
elif os.path.isdir(item_path):
# 递归处理更深层次的子文件夹
zip_subdirectory(item_path, zip_file, root_basename)
# 使用示例
if __name__ == "__main__":
# 要压缩的根文件夹路径
root_folder = "dir_level_1"
# 压缩文件保存路径
zip_path = "dir_level_1.zip"
# 确保根文件夹存在
if not os.path.isdir(root_folder):
print(f"错误: 文件夹 '{root_folder}' 不存在")
else:
# 创建并打开zip文件,使用deflated模式进行压缩
with zipfile.zipfile(zip_path, 'w', zipfile.zip_deflated) as zipf:
zip_directory(root_folder, zipf)
print(f"压缩完成,文件保存为: {zip_path}")
到此这篇关于python3中使用zipfile进行文件的压缩和解压缩实现的文章就介绍到这了,更多相关python3 zipfile压缩和解压缩内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论