Python 标准库提供了多个用于数据压缩的模块,包括:
zlib
、gzip
、bz2
、zipfile
、tarfile
。
这些模块可以处理不同格式的压缩文件和压缩数据流。
目录
1. zlib 模块
zlib
模块提供了对 zlib 库的访问,用于数据的压缩和解压缩。
基本用法
import zlib
# 压缩数据
data = b"Some data to compress" * 100
compressed_data = zlib.compress(data)
print(f"原始大小: {len(data)}, 压缩后: {len(compressed_data)}")
# 解压数据
decompressed_data = zlib.decompress(compressed_data)
assert data == decompressed_data
高级功能
# 使用压缩级别 (0-9)
compressed = zlib.compress(data, level=9)
# 创建压缩/解压缩对象
compressor = zlib.compressobj(level=9)
chunk1 = compressor.compress(data[:100])
chunk2 = compressor.compress(data[100:])
final_chunk = compressor.flush()
decompressor = zlib.decompressobj()
result = decompressor.decompress(chunk1 + chunk2 + final_chunk)
2. gzip 模块
gzip
模块提供了对 GNU zip 文件的读写接口。
读写 gzip 文件
import gzip
import shutil
# 写入 gzip 文件
with gzip.open('example.txt.gz', 'wb') as f:
f.write(b"Some data to compress" * 100)
# 读取 gzip 文件
with gzip.open('example.txt.gz', 'rb') as f:
content = f.read()
print(content)
# 压缩现有文件
with open('large_file.txt', 'rb') as f_in:
with gzip.open('large_file.txt.gz', 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
3. bz2 模块
bz2
模块提供了对 bzip2 压缩算法的支持。
基本用法
import bz2
# 压缩数据
data = b"Some data to compress" * 100
compressed = bz2.compress(data)
print(f"压缩率: {len(compressed)/len(data):.1%}")
# 解压数据
decompressed = bz2.decompress(compressed)
assert data == decompressed
# 文件操作
with bz2.open('example.bz2', 'wb') as f:
f.write(b"This is a bzip2 compressed file")
4. zipfile 模块
zipfile
模块用于处理 ZIP 归档文件。
创建 ZIP 文件
import zipfile
# 创建 ZIP 文件并添加文件
with zipfile.ZipFile('archive.zip', 'w') as zipf:
zipf.write('file1.txt')
zipf.write('file2.txt', arcname='renamed.txt') # 指定归档中的名称
# 添加目录
with zipfile.ZipFile('archive.zip', 'w') as zipf:
zipf.write('my_directory') # 添加整个目录
读取 ZIP 文件
# 列出 ZIP 文件内容
with zipfile.ZipFile('archive.zip', 'r') as zipf:
print(zipf.namelist()) # 列出所有文件
# 提取单个文件
zipf.extract('file1.txt', 'extract_dir')
# 提取所有文件
zipf.extractall('extract_all_dir')
# 读取 ZIP 中的文件内容
with zipfile.ZipFile('archive.zip') as zipf:
with zipf.open('file1.txt') as f:
content = f.read()
print(content)
5. tarfile 模块
tarfile
模块用于处理 tar 归档文件,支持 gzip 和 bzip2 压缩。
创建 tar 归档
import tarfile
# 创建未压缩的 tar 文件
with tarfile.open('archive.tar', 'w') as tar:
tar.add('file1.txt')
tar.add('my_directory')
# 创建 gzip 压缩的 tar 文件
with tarfile.open('archive.tar.gz', 'w:gz') as tar:
tar.add('file1.txt')
# 创建 bzip2 压缩的 tar 文件
with tarfile.open('archive.tar.bz2', 'w:bz2') as tar:
tar.add('file1.txt')
读取 tar 归档
# 列出 tar 文件内容
with tarfile.open('archive.tar.gz', 'r:gz') as tar:
print(tar.getnames()) # 列出所有成员
# 提取单个文件
tar.extract('file1.txt', 'extract_dir')
# 提取所有文件
tar.extractall('extract_all_dir')
# 读取 tar 中的文件内容
with tarfile.open('archive.tar.gz', 'r:gz') as tar:
member = tar.getmember('file1.txt')
f = tar.extractfile(member)
content = f.read()
print(content)
6. 性能比较与选择建议
-
zlib/gzip:
-
压缩速度较快
-
压缩率中等
-
适合网络传输和一般文件压缩
-
-
bz2:
-
压缩速度较慢
-
压缩率较高
-
适合需要高压缩率且不频繁访问的场景
-
-
zipfile:
-
支持多文件归档
-
广泛兼容
-
适合打包多个文件
-
-
tarfile + 压缩:
-
保留文件权限和元数据
-
适合 Unix/Linux 系统备份
-
结合 gzip/bzip2 提供压缩功能
-
6. 实际应用示例
1. 压缩日志文件
import gzip
import shutil
from pathlib import Path
def compress_logs(log_dir, output_dir):
output_dir = Path(output_dir)
output_dir.mkdir(exist_ok=True)
for log_file in Path(log_dir).glob('*.log'):
with open(log_file, 'rb') as f_in:
with gzip.open(output_dir / f"{log_file.name}.gz", 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
print(f"Compressed {log_file} to {output_dir/log_file.name}.gz")
2. 创建加密的 ZIP 文件
import zipfile
import os
def create_encrypted_zip(output_filename, files_to_zip, password):
with zipfile.ZipFile(output_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
for file in files_to_zip:
zipf.write(file, arcname=os.path.basename(file))
# 设置密码 (Python 3.6+)
zipf.setpassword(password.encode('utf-8'))
print(f"Created encrypted archive: {output_filename}")
3. 增量备份目录
import tarfile
import time
import os
def incremental_backup(source_dir, backup_file):
# 只备份最近修改的文件
cutoff = time.time() - 24 * 3600 # 24小时前
with tarfile.open(backup_file, 'w:gz') as tar:
for root, dirs, files in os.walk(source_dir):
for file in files:
path = os.path.join(root, file)
mtime = os.path.getmtime(path)
if mtime > cutoff:
tar.add(path)
print(f"Added {path} to backup")
注意事项
-
内存使用:处理大文件时,考虑分块处理避免内存不足
-
文件权限:解压时注意文件权限设置,特别是在跨平台场景
-
路径安全:处理压缩文件时注意路径遍历攻击风险
-
编码问题:处理文件名时注意编码问题,特别是跨平台场景
-
资源清理:确保正确关闭文件句柄,使用
with
语句管理资源
这些压缩模块为 Python 提供了强大的数据压缩和归档功能,可以根据具体需求选择合适的模块和压缩算法。