在python中解压缩嵌套的zip文件

djm*_*mac 9 python zip

我正在寻找一种在python中解压缩嵌套zip文件的方法.例如,考虑以下结构(为了方便起见,假设名称):

    • ZipfileA.zip
      • ZipfileA1.zip
      • ZipfileA2.zip
    • ZipfileB.zip
      • ZipfileB1.zip
      • ZipfileB2.zip

...等等.我正在尝试访问第二个zip中的文本文件.我当然不想提取所有东西,因为剪切数会使计算机崩溃(第一层有几百个拉链,第二层有几乎10,000个(每个拉链)).

我一直在使用'zipfile'模块 - 我可以打开第一级zipfiles.例如:

zipfile_obj = zipfile.ZipFile("/Folder/ZipfileA.zip")
next_layer_zip = zipfile_obj.open("ZipfileA1.zip")
Run Code Online (Sandbox Code Playgroud)

但是,这会返回一个"ZipExtFile"实例(不是文件或zipfile实例) - 然后我就不能继续打开这个特定的数据类型.我不能这样做:

data = next_layer_zip.open(data.txt)
Run Code Online (Sandbox Code Playgroud)

然而,我可以"读取"此zip文件文件:

next_layer_zip.read()
Run Code Online (Sandbox Code Playgroud)

但这完全没用!(即只能读取压缩数据/ goobledigook).

有没有人对我如何解决这个问题有任何想法(使用ZipFile.extract)?

我遇到过这个问题,http://pypi.python.org/pypi/zip_open/ - 它看起来完全符合我的要求,但它似乎对我不起作用.(继续获取"[Errno 2]没有这样的文件或目录:"对于我正在尝试处理的文件,使用该模块).

任何想法将不胜感激!! 提前致谢

小智 10

我使用Python 3.7.3

import zipfile
import io
with zipfile.ZipFile('all.zip') as z:
    with z.open('nested.zip') as z2:
        z2_filedata =  io.BytesIO(z2.read())
        with zipfile.ZipFile(z2_filedata) as nested_zip:
            print( nested_zip.open('readme.md').read())
Run Code Online (Sandbox Code Playgroud)


小智 9

ZipFile需要一个类文件对象,因此您可以使用StringIO将您从嵌套zip读取的数据转换为这样的对象.需要注意的是,您将把完整(仍然压缩的)内部zip加载到内存中.

with zipfile.ZipFile('foo.zip') as z:
    with z.open('nested.zip') as z2:
        z2_filedata = cStringIO.StringIO(z2.read())
        with zipfile.ZipFile(z2_filedata) as nested_zip:
            print nested_zip.open('data.txt').read()
Run Code Online (Sandbox Code Playgroud)


Ign*_*ams 8

不幸的是,解压缩zip文件需要随机访问存档,而ZipFile方法(更不用说DEFLATE算法本身)只提供流.因此,不解压缩嵌套的zip文件是不可能的.


ron*_*ydw 8

对于那些正在寻找提取嵌套 zip 文件(任何级别的嵌套)并清理原始 zip 文件的函数的人:

import zipfile, re, os

def extract_nested_zip(zippedFile, toFolder):
    """ Unzip a zip file and its contents, including nested zip files
        Delete the zip file(s) after extraction
    """
    with zipfile.ZipFile(zippedFile, 'r') as zfile:
        zfile.extractall(path=toFolder)
    os.remove(zippedFile)
    for root, dirs, files in os.walk(toFolder):
        for filename in files:
            if re.search(r'\.zip$', filename):
                fileSpec = os.path.join(root, filename)
                extract_nested_zip(fileSpec, root)
Run Code Online (Sandbox Code Playgroud)


Mat*_*aus 6

这是我想出的一个功能.

def extract_nested_zipfile(path, parent_zip=None):
    """Returns a ZipFile specified by path, even if the path contains
    intermediary ZipFiles.  For example, /root/gparent.zip/parent.zip/child.zip
    will return a ZipFile that represents child.zip
    """

    def extract_inner_zipfile(parent_zip, child_zip_path):
        """Returns a ZipFile specified by child_zip_path that exists inside
        parent_zip.
        """
        memory_zip = StringIO()
        memory_zip.write(parent_zip.open(child_zip_path).read())
        return zipfile.ZipFile(memory_zip)

    if ('.zip' + os.sep) in path:
        (parent_zip_path, child_zip_path) = os.path.relpath(path).split(
            '.zip' + os.sep, 1)
        parent_zip_path += '.zip'

        if not parent_zip:
            # This is the top-level, so read from disk
            parent_zip = zipfile.ZipFile(parent_zip_path)
        else:
            # We're already in a zip, so pull it out and recurse
            parent_zip = extract_inner_zipfile(parent_zip, parent_zip_path)

        return extract_nested_zipfile(child_zip_path, parent_zip)
    else:
        if parent_zip:
            return extract_inner_zipfile(parent_zip, path)
        else:
            # If there is no nesting, it's easy!
            return zipfile.ZipFile(path)
Run Code Online (Sandbox Code Playgroud)

这是我测试它的方式:

echo hello world > hi.txt
zip wrap1.zip hi.txt
zip wrap2.zip wrap1.zip
zip wrap3.zip wrap2.zip

print extract_nested_zipfile('/Users/mattfaus/dev/dev-git/wrap1.zip').open('hi.txt').read()
print extract_nested_zipfile('/Users/mattfaus/dev/dev-git/wrap2.zip/wrap1.zip').open('hi.txt').read()
print extract_nested_zipfile('/Users/mattfaus/dev/dev-git/wrap3.zip/wrap2.zip/wrap1.zip').open('hi.txt').read()
Run Code Online (Sandbox Code Playgroud)