Python工具箱系列(四十四)

发布时间 2023-10-23 14:19:39作者: 西安衍舆航天

使用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库相当于加了一个壳,从而使分卷与组卷的过程对于文件的打开与读入来说是透明的,使用起来非常方便。