Python工具箱系列(四十四)
使用py7zr对目录与文件进行压缩打包
7z是一种主流高效的压缩格式,它拥有极高的压缩比。在计算机科学中,7z是一种可以使用多种压缩算法进行数据压缩的档案格式。该格式最初被7-Zip实现并采用,但是这种档案格式是公有的,并且7-Zip软件本身亦在GNU宽通用公共许可证(GNU LGPL)协议下开放源代码。LZMA软件开发工具包的最新版本为V9.34。7z格式的MIME类型为application/x-7z-compressed。通常使用7-Zip的7z格式能比使用zip格式的压缩文件小30-70%。并且使用7-Zip创建的zip格式比大多数其它压缩软件创建的都小2-10%。7z已公开了结构编辑功能,所以它可以支持任何一种新的压缩算法。类似于视频格式中的mkv,7z能够包容多种算法,目前下列压缩算法已被整合到了7z中:
压缩算法 |
备注 |
LZMA |
改良与优化后的 LZ77 算法 |
LZMA2 |
改良的 LZMA 算法 |
PPMD |
基于 Dmitry Shkarin 的 PPMdH 算法 |
BCJ |
32 位 x86 可执行文件转换程序 |
BCJ2 |
32 位 x86 可执行文件转换程序 |
BZip2 |
标准 BWT 算法 |
Deflate |
标准 LZ77-based 算法 |
LZMA算法是7z格式的默认算法。LZMA算法具有以下主要特征:
◆高压缩比
◆可变字典大小
◆支持利用多CPU
◆LZMA压缩算法非常适于应用程序的内嵌。LZMA发布于GNU LGPL许可协议之下
在python中使用它,需要进行一些必要的安装如下:
pip install py7zr
pip install multivolumefile
以下代码示例对7z的使用:
import py7zr
import multivolumefile
targetfile = 'archive.7z'
# 压缩目录下所有文件,并且设置口令
with py7zr.SevenZipFile(targetfile, 'w', password='8848') as archive:
# 压缩整个目录下文件,由于这个库存在BUG,所以只能够使用相对路径
archive.writeall("gotoolkits/markdown")
# 单个文件
archive.write("gotoolkits/README.md")
# 解压出所有文件
with py7zr.SevenZipFile(targetfile, 'r', password='8848') as archive:
archivelist = archive.list()
# 显示压缩包中的所有文件信息
for fileinfo in archivelist:
print(fileinfo.filename)
archive.extractall('../test')
# 创建一个多卷的压缩文件
with multivolumefile.open(targetfile, mode='wb', volume=1024) as target_archive:
with py7zr.SevenZipFile(target_archive, 'w') as archive:
archive.writeall("gotoolkits/markdown")
# 从多卷的压缩文件中释放所有文件
with multivolumefile.open(targetfile, mode='rb') as target_archive:
with py7zr.SevenZipFile(target_archive, 'r') as archive:
archive.extractall('../test/multi')
由于py7zr还处在成熟阶段,所以还有缺陷。无论是压缩文件还是文件,必须以当前工作目录为基准的相对路径。同样,解压缩时也需要以当前工作目录为基础的相对路径,默认均以工作目录为当前路径。这个代码有趣之处是引入了multivolumefile这个第三方库,它不仅能够支持类似对zip/tar/7z的分卷支持,其实任何文件都可以分卷。例如以下代码演示了对pdf文档的分卷操作:
import multivolumefile
targetfilename = '数学之美.pdf'
mvfilename = 'archive.pdf'
# 10M形成一个卷
with multivolumefile.open(mvfilename, mode = 'wb', volume=1024*1024*10) as vol:
with open(targetfilename, 'rb') as pdf:
vol.write(pdf.read())
# 用多卷重新生成原文档
with multivolumefile.open(mvfilename, 'rb') as vol:
with open(f'{targetfilename}.back','wb') as ouput:
ouput.write(vol.read())
从代码中可以看到,multvolumefile库相当于加了一个壳,从而使分卷与组卷的过程对于文件的打开与读入来说是透明的,使用起来非常方便。