2008-12-03 6 views
15

Mit Python 2.4 und der integrierten Bibliothek ZipFile kann ich sehr große ZIP-Dateien (größer als 1 oder 2 GB) nicht lesen, da der gesamte Inhalt der nicht komprimierten Datei im Arbeitsspeicher gespeichert werden soll. Gibt es einen anderen Weg dies zu tun (entweder mit einer Drittanbieter-Bibliothek oder einem anderen Hack), oder muss ich es auf diese Weise "auspacken" und entzippen (was natürlich nicht so plattformübergreifend ist).Wie entpacken Sie sehr große Dateien in Python?

Antwort

16

Hier ist ein Überblick über die Dekomprimierung großer Dateien.

import zipfile 
import zlib 
import os 

src = open(doc, "rb") 
zf = zipfile.ZipFile(src) 
for m in zf.infolist(): 

    # Examine the header 
    print m.filename, m.header_offset, m.compress_size, repr(m.extra), repr(m.comment) 
    src.seek(m.header_offset) 
    src.read(30) # Good to use struct to unpack this. 
    nm= src.read(len(m.filename)) 
    if len(m.extra) > 0: ex= src.read(len(m.extra)) 
    if len(m.comment) > 0: cm= src.read(len(m.comment)) 

    # Build a decompression object 
    decomp= zlib.decompressobj(-15) 

    # This can be done with a loop reading blocks 
    out= open(m.filename, "wb") 
    result= decomp.decompress(src.read(m.compress_size)) 
    out.write(result) 
    result = decomp.flush() 
    out.write(result) 
    # end of the loop 
    out.close() 

zf.close() 
src.close() 
+0

Genau das habe ich gesucht - danke! –

+1

@ s-lott Was bedeutet 'ex = src.read (len (m.extra))' und 'cm = src.read (len (m.comment))' was benutzt du die Variablen 'ex' und' cm 'für? Was meinst du, es ist gut, eine Struktur zu verwenden, um dies zu entpacken? Und wofür wird die magische Zahl "30" verwendet? – Jonathan

8

Ab Python 2.6 können Sie ZipFile.open() verwenden, um einen Datei-Handle auf eine Datei zu öffnen und Inhalte effizient in eine Zieldatei Ihrer Wahl kopieren:

import errno 
import os 
import shutil 
import zipfile 

TARGETDIR = '/foo/bar/baz' 

with open(doc, "rb") as zipsrc: 
    zfile = zipfile.ZipFile(zipsrc) 
    for member in zfile.infolist(): 
     target_path = os.path.join(TARGETDIR, member.filename) 
     if target_path.endswith('/'): # folder entry, create 
      try: 
       os.makedirs(target_path) 
      except (OSError, IOError) as err: 
       # Windows may complain if the folders already exist 
       if err.errno != errno.EEXIST: 
        raise 
      continue 
     with open(target_path, 'wb') as outfile, zfile.open(member) as infile: 
      shutil.copyfileobj(infile, outfile) 

Dies verwendet shutil.copyfileobj() effizient zu lesen Daten aus dem geöffneten ZIP-Dateiobjekt und kopieren es in die Ausgabedatei.