it-swarm.com.de

Wie liest man aus einer Zip-Datei in einer Zip-Datei in Python?

Ich möchte eine Datei lesen, die selbst in einem Zip-Archiv komprimiert ist. Zum Beispiel enthält parent.Zip child.Zip, das child.txt enthält. Ich habe Probleme beim Lesen des Kindes.Zip. Kann jemand meinen Code korrigieren?

Ich gehe davon aus, dass ich child.Zip als dateiähnliches Objekt erstellen und es dann mit einer zweiten Instanz von zipfile öffnen muss, aber wenn ich neu in Python bin, ist mein zipfile.ZipFile (zfile.open (name)) albern. Es löst eine zip-Datei aus.BadZip-Datei: "Datei ist keine zip-Datei" auf child.Zip (unabhängig validiert)

import zipfile
with zipfile.ZipFile("parent.Zip", "r") as zfile:
    for name in zfile.namelist():
        if re.search(r'\.Zip$', name) != None:
            # We have a Zip within a Zip
            with **zipfile.ZipFile(zfile.open(name))** as zfile2:
                    for name2 in zfile2.namelist():
                        # Now we can extract
                        logging.info( "Found internal internal file: " + name2)
                        print "Processing code goes here"
29

Wenn Sie den Aufruf .open() in einer ZipFile-Instanz verwenden, wird tatsächlich ein offener Datei-Handle angezeigt. Um read a Zip-Datei zu benötigen, benötigt die ZipFile-Klasse jedoch etwas mehr. Es muss in der Lage sein, seek für diese Datei und das von .open() zurückgegebene Objekt ist nicht suchbar.

Um das Problem zu umgehen, lesen Sie den gesamten Zip-Eintrag mit .read() in den Speicher, speichern ihn in einem BytesIO-Objekt (einer In-Memory-Datei, die ist durchsuchbar), und geben Sie diese an ZipFile

from io import BytesIO

# ...
        zfiledata = BytesIO(zfile.read(name))
        with zipfile.ZipFile(zfiledata) as zfile2:

oder im Zusammenhang mit Ihrem Beispiel:

import zipfile
from io import BytesIO

with zipfile.ZipFile("parent.Zip", "r") as zfile:
    for name in zfile.namelist():
        if re.search(r'\.Zip$', name) != None:
            # We have a Zip within a Zip
            zfiledata = BytesIO(zfile.read(name))
            with zipfile.ZipFile(zfiledata) as zf
                for name2 in zfile2.namelist():
                    # Now we can extract
                    logging.info( "Found internal internal file: " + name2)
                    print "Processing code goes here"
39
Martijn Pieters

Damit dies mit python33 funktioniert (unter Windows, aber das ist vielleicht nicht relevant), musste ich Folgendes tun:

 import zipfile, re, io
    with zipfile.ZipFile(file, 'r') as zfile:
        for name in zfile.namelist():
            if re.search(r'\.Zip$', name) != None:
                zfiledata = io.BytesIO(zfile.read(name))
                with zipfile.ZipFile(zfiledata) as zfile2:
                    for name2 in zfile2.namelist():
                        print(name2)

cStringIO existiert nicht, also habe ich io.BytesIO verwendet

8
zlr

Hier ist eine Funktion, die ich mir ausgedacht habe. (Kopiert von hier .)

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)

So habe ich es getestet:

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()
0
Matt Faus