7z文件解压、压缩、分包
本文将介绍关于使用py7zr的一些技巧
创建带有加密的7z压缩包¶
Python
import py7zr
from py7zr import FILTER_LZMA2
filters = [{'id': FILTER_LZMA2, 'preset': 9}]
# 这里需要定义解压类型,如果不定义的话,如果使用的类型是极限压缩的话,容易出现编码问题
with open('password', 'r') as f:
password = str(f.read())
# 将密码从文本文档中读取出来,因为默认是列表,所以转换一下
with py7zr.SevenZipFile("D:\\python\\result.7z", mode='r', password=password, filters=filters) as z:
z.extractall(path=r'D:\\python\\')
Note
通过目前的测试来看,如果密码含有特殊符号,还是从文档中读取并作为密码,既能贴合现实情况,也能规避一些特殊符号带来的转换问题
Warning
一定要注意压缩文件的编码类型,选择不当会出现问题,还有密码也需要检查清楚,否则会报错,而且都没法看出是哪里出现了问题
压缩分卷解压¶
如果要对压缩分包进行解压,该如何处理?
Python
import py7zr
# 获取所有压缩分包的名字
filenames = ['example.7z.0001', 'example.7z.0002']
# 将压缩分包合并到一个压缩包中,其中 result.7z是作为中转用的
with open('result.7z', 'ab') as outfile:
for fname in filenames:
# 因为压缩包属于二进制文件,所以这里不能用常规的w或r,而是需要用到b
with open(fname, 'rb') as infile:
outfile.write(infile.read())
# 正常解压压缩包即可
with py7zr.SevenZipFile("result.7z", "r") as archive:
archive.extractall()
# 查了一下官方说明,这个和os.remove方法是类似的,主要作用是用来删除中转的文件
os.unlink("result.7z)
1125更新
如果是处理压缩分卷的话,不一定需要像以上那样去合并后处理,可以直接处理,参考代码如下:
Python
def _extract_7z_coiling_file(file_path: str, target_path: str) -> bool:
"""提取7z压缩分卷"""
start_filename_no_suffix: str = os.path.splitext(os.path.basename(file_path))[0]
# 不带有后缀名的文件名称
try:
with multivolumefile.open(
os.path.join(os.path.dirname(file_path), start_filename_no_suffix), "rb"
) as target_archive:
with SevenZipFile(
target_archive, # type:ignore
"r",
filters=CommonVariable.filters,
) as archive:
archive.extractall(path=target_path)
return True
except Exception as e:
customLogger.info(f"提取7z压缩分卷失败,提示为{e}")
return False
创建压缩分卷¶
如果要对某个文件夹进行压缩分包,该如何处理?
Python
import multivolumefile
import py7zr
import pathlib
target = pathlib.Path('D:\python\python-3.10.6-docs-html')
with multivolumefile.open('example.7z', mode='wb', volume=int(10240*1024/2),) as target_archive:
with py7zr.SevenZipFile(target_archive, 'w') as archive:
archive.writeall(target, 'target')
Note
官方手册中的参考代码有问题,现在open传入的参数只能是 volume ,不是 volume_size ,这个只能通过看源代码才能发现,而且 volume 参数默认是按字节进行计算的的,需要注意换算
如果按照上面的代码生成压缩分包,结果生成的压缩分包的编号是4位数,那怎么自定义编号数量了?
通过研究multivolumefile模块,最终发现可以不使用open(),直接调用其类就可以了,参考代码如下:
Note
如果想要使用py7zr压缩比较大的文件的话,不建议使用这个模块,经过测试发现它比原生的7-zip要慢上2-3倍,暂时还没有好的解决办法,暂时放在这里做个记录