如何在 Python 中解压多部分存档 (zip/rar)?

How can I unpack multi-part archives (zip/rar) in Python?

我有一个 2 GB 的归档文件(最好是 .zip 或 .rar)文件(假设 100 个部分 x 20MB),我正在尝试找到一种正确解压缩它的方法。我从一个 .zip 存档开始;我有 test.zip、test.z01、test.z02...test.99 等文件。当我像这样将它们合并到 Python 中时:

for zipName in zips:
     with open(os.path.join(path_to_zip_file, "test.zip"), "ab") as f:
         with open(os.path.join(path_to_zip_file, zipName), "rb") as z:
             f.write(z.read())

然后,合并后,像 thod 一样解压它

with zipfile.ZipFile(os.path.join(path_to_zip_file, "test.zip"), "r") as zipObj:
     zipObj.extractall(path_to_zip_file)

我收到错误,likr

test.zip file isn't zip file.

然后我尝试使用 .rar 存档。我试图只解压缩第一个文件,看看我的代码是否会智能地查找并提取剩余的存档片段,但它没有。所以我再次合并了 .rar 文件(就像在 .zip 的情况下一样),然后尝试使用 patoolib:

解压缩它
patoolib.extract_archive("test.rar", outdir="path here")

当我这样做时,我收到如下错误:

patoolib.util.PatoolError: could not find an executable program to extract format rar; candidates are (rar,unrar,7z)

经过一些工作,我发现这些合并文件已损坏(我复制它并尝试使用 WinRAR 在 windows 上正常解压,但遇到了一些问题)。所以我尝试了其他合并方式,例如使用 cat cat test.part.* >test.rar,但这些都没有帮助。

如何在 Python 中正确合并然后解压缩这些存档文件?

从 python

调用 7z
  1. .zip 重命名为 .zip.001,将 .z01 重命名为 zip.002 等等。
  2. 001 ( 7z x test.zip.001 )
  3. 上致电 7z
import subprocess
cmd = ['7z', 'x', 'test.zip.001']
sp = subprocess.Popen(cmd, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)

cat test.zip* > test.zip 也应该有效,但并不总是恕我直言。对单个文件进行了尝试并有效,但对子文件夹失败了。必须保持正确的顺序。

测试:

7z -v1m a test.zip 12MFile
cat test.zip* > test.zip
7z t test.zip
>> Everything is Ok

无法检查“官方”WinRAR(这是否还存在?!)和 WinZIP 文件。

合并 Python

中的文件

如果你想留在 python 这也适用(同样适用于我的 7z 测试文件..):

import shutil
import glob

with open('output_file.zip','wb') as wfd:
    for f in glob.glob('test.zip.*'): # Search for all files matching searchstring
        with open(f,'rb') as fd:
            shutil.copyfileobj(fd, wfd) # Concatinate

进一步说明

  • pyunpack(python 前端)与 patool(python 后端)并安装了 unrarp7zip-rar(7z 与 unfree linux 或 windows 中的 7z 的 rar-stuff) 可以处理 python
  • 中的 zip 和 rar(以及更多)
  • 有一个 7z x -t 标志用于明确将其设置为拆分存档(如果文件未命名为 001 可能会有帮助)。举个例子7z x -trar.split7z x -tzip.split 之类的。