Python - 从大型(6GB +)zip文件中提取文件

Bre*_*ett 3 python compression zlib zipfile

我有一个Python脚本,我需要提取ZIP文件的内容.但是,zip文件大小超过6GB.

有很多关于zlibzipfile模块的信息,但是,我无法找到适用于我的情况的单一方法.我有代码:

with zipfile.ZipFile(fname, "r") as z:
        try:
            log.info("Extracting %s " %fname)
            head, tail = os.path.split(fname)
            z.extractall(folder + "/" + tail)
        except zipfile.BadZipfile:
            log.error("Bad Zip file")
        except zipfile.LargeZipFile:
            log.error("Zip file requires ZIP64 functionality but that has not been enabled (i.e., too large)")
        except zipfile.error:
            log.error("Error decompressing ZIP file")
Run Code Online (Sandbox Code Playgroud)

我知道我需要设置allowZip64,true但我不确定如何做到这一点.然而,即使是这样,LargeZipFile也不会抛出异常,而是BadZipFile例外.我不知道为什么.

另外,这是处理提取6GB zip存档的最佳方法吗?

更新:修改此BadZipfile例外:

except zipfile.BadZipfile as inst:
        log.error("Bad Zip file")
        print type(inst)     # the exception instance
        print inst.args      # arguments stored in .args
        print inst
Run Code Online (Sandbox Code Playgroud)

说明:

<class 'zipfile.BadZipfile'>
('Bad magic number for file header',)
Run Code Online (Sandbox Code Playgroud)

更新#2:

完整的追溯显示

BadZipfile                                Traceback (most recent call last)
<ipython-input-1-8d34a9f58f6a> in <module>()
      6     for member in z.infolist():
      7         print member.filename[-70:],
----> 8         f = z.open(member, 'r')
      9         size = 0
     10         while True:

/Users/brspurri/anaconda/python.app/Contents/lib/python2.7/zipfile.pyc in open(self, name, mode, pwd)
    965             fheader = struct.unpack(structFileHeader, fheader)
    966             if fheader[_FH_SIGNATURE] != stringFileHeader:
--> 967                 raise BadZipfile("Bad magic number for file header")
    968 
    969             fname = zef_file.read(fheader[_FH_FILENAME_LENGTH])

BadZipfile: Bad magic number for file header
Run Code Online (Sandbox Code Playgroud)

运行代码:

import sys
import zipfile

with open(zip_filename, 'rb') as zf:
    z = zipfile.ZipFile(zf, allowZip64=True)
    z.testzip()

doesn't output anything.
Run Code Online (Sandbox Code Playgroud)

aba*_*ert 7

问题是你有一个损坏的zip文件.我可以在下面添加有关腐败的更多细节,但首先是实际的东西:

您可以使用此代码段告诉您存档中的哪个成员已损坏.但是,print z.testzip()已经告诉过你同样的事了.和zip -T或者unzip在命令行上也应该给您提供相应的冗长该信息.


那么,你怎么办呢?

好吧,显然,如果你能得到一份未经破坏的文件副本,那就去做吧.

如果没有,如果你想跳过坏文件并提取其他所有内容,这很容易 - 大多数代码与上面链接的代码段相同:

with open(sys.argv[1], 'rb') as zf:
    z = zipfile.ZipFile(zf, allowZip64=True)
    for member in z.infolist():
        try:
            z.extract(member)
        except zipfile.error as e:
            # log the error, the member.filename, whatever
Run Code Online (Sandbox Code Playgroud)

Bad magic number for file header异常消息意味着zipfile能够成功打开压缩文件,解析它的目录,找到一个成员的信息,寻求到存档内的成员,和读的成员,所有这些都使头部意味着你可能没有zip64-相关问题在这里.但是,当它读取该标题时,它没有预期的"魔术"签名PK\003\004.这意味着存档已损坏.

腐败恰好恰好是4294967296,这一事实非常强烈地表明你在链的某个地方遇到了64位问题,因为那正好是2**32.


命令行zip/ unzip工具有一些解决方法来处理导致此类问题的腐败的常见原因.看起来这些变通办法可能适用于此存档,因为您收到警告,但所有文件都显然已恢复.Python的zipfile库没有那些解决方法,我怀疑你想自己编写自己的zip代码...

然而,这确实为两种可能性打开了大门:

首先,zip也许可以使用of flag 修复 zip文件.(如果您需要帮助,请阅读联机帮助页,或者在SuperUser等网站上询问.)-F-FFzip -h

如果所有其他方法都失败了,您可以unzip从Python 运行该工具,而不是使用zipfile,如下所示:

subprocess.check_output(['unzip', fname])
Run Code Online (Sandbox Code Playgroud)

当然,这比zipfile模块提供的灵活性和功率要低得多- 但是你并没有使用任何灵活性; 你只是打电话extractall.