Eine ZIP-Datei ist ein Container- und Archive-Format, das eine verlustfreie Komprimierung von Dateien ermöglicht. Deshalb wird es gerne für Backups verwendet oder für das Versenden mehrerer Dateien per E-Mail; hier dann als Container für die Daten.
So lässt sich das ZIP-Format auch für größere Archive verwenden, die selten geöffnet werden - wo somit Speicher gespart werden kann.
Dieses Container- bzw. Archive-Format können wir auch in Python verwenden. In dieser Anleitung will ich dir einen Überblick geben, wie du mit dem ZIP-Format in Python arbeiten kannst. Also wie du ZIP-Dateien einlesen und wie du einen Ordner zippen kannst.
Falls du dich mehr für PHP interessierst, habe ich noch einen ähnlichen Artikel zu dem Thema für PHP verfasst. Diesen findest du hier: "Arbeiten in PHP mit ZIP-Archiven".
Einen Ordner als ZIP-Datei zu verpacken ist mit dem Paket zipfile
möglich. In Python es gibt leider keine Standard-Methode, um einfach den Ordner zu zippen, sondern es ist notwendig, jede Datei einzeln abzulegen. Um das zu realisieren, verwenden wir zusätzlich das Modul OS um alle Dateien aus dem Python-Verzeichnis und darunter liegenden Ordnern in die ZIP-Datei zu inkludieren.
Als Beispiel habe ich eine kleine Funktion geschrieben. Diese erwartet 2 Parameter, kann aber auch einen optionalen dritten entgehen nehmen.
Innerhalb der Funktion öffnen wir als Erstes eine neue ZIP-Datei mit Context Manager erstellen. Das heißt, wir verwenden das with
-Keyword. Die Verwendung mit Context Manager funktioniert ab Python 3.2. Mit der Methode write
können neue Dateien in das ZIP-Archive eingefügt werden. Mittels der Methode os.walk
können wir über ein Verzeichnis iterieren und alle Dateien erhalten. Mehr dazu im Artikel "In Python Verzeichnisse einlesen".
Zusätzlich lassen wir uns im Terminal noch anzeigen, welche Dateien in das ZIP-Archive eingefügt worden sind.
import os,zipfile
def createZIP(folder,filename,compress = zipfile.ZIP_DEFLATED):
# ZIP Archive Öffnen
with zipfile.ZipFile(filename + '.zip', 'w', compress) as target:
for root, dirs, files in os.walk(folder):
for file in files:
add = os.path.join(root, file)
# Datei zum ZIP Archive Hinzufügen
target.write(add)
print(add + ' wurde Hinzugefügt')
# ZIP Archive vom Verzeichnis "bilder" erstellen.
createZIP('bilder','bilder-archive')
Und so einfach können wir nun vom Verzeichnis "bilder" ein ZIP-Archive erstellen und danach zum Beispiel als E-Mail versenden.
Das Extrahieren von ZIP-Files funktioniert sehr einfach. Als erstes öffnen wir die Datei wieder mit Context Manager (ab Python 3.2). Danach können wir die Methode extractall
verwenden und ein Verzeichnis angeben, in dem das ZIP-Archive entpackt werden soll. Beim Öffnen solltest du den Modus r
fürs Lesen nehmen.
import zipfile
with zipfile.ZipFile('example.zip','r') as source:
source.extractall('bilder-archive')
So kannst du nun schnell und einfach eine ZIP-Datei in einen Ordner entpacken. Alternativ, falls du eine ältere Version von Python verwendest, geht es auch ganz einfach ohne Context Manager; und zwar wie folgt:
import zipfile
source = zipfile.ZipFile('example.zip','r')
source.extractall('bilder-archive')
source.close()
Der Vorteil am Context Manager ist, dass du die ZIP-Datei nicht mehr abschließend schließen brauchst, da der Manager das selbständig beim Verlassen der Einrückung macht.
Manchmal kommt es vor, dass du zum Beispiel Dateien aus einer ZIP-Datei verwenden willst, zum Beispiel für ein Import-Tool. Aber du willst diese nicht vorher extrahieren, weil du den Ordner am Ende nur wieder Löschen würdest? Das kannst du auch tun mit der read
-Methode. Oder wenn du ein File-Objekt haben willst, kannst du auch die Methode open
mit Pfadangabe verwenden.
Und vorher willst du noch wissen, welche Dateien in deinem ZIP-Archive überhaupt vorhanden sind? Das kannst du mit der Methode namelist
herausfinden.
In unserem Beispiel verwenden wir noch die Methode decode
, um die binären Daten in eine String umzuwandeln.
import zipfile
with zipfile.ZipFile('bilder-archive.zip','r') as source:
# Erhalte eine Liste mit alle Dateien die in dem ZIP Vorhanden sind
print(source.namelist())
# Ein Bestimmte Datei aus dem ZIP Lesen und in einen String Convertieren
print(source.read('bilder/test.txt').decode('utf-8'))
Das Extrahieren von Dateien mit Passwörtern funktioniert genauso einfach wie ohne:
Es wird bei der Methode extractall
ein zweiter Parameter pwd
übergeben. Dieser erwartet bytes, weshalb wir unseren String in bytes konvertieren müssen. Danach ist das ZIP-Archive mit Passwortschutz entpackt.
import zipfile
with zipfile.ZipFile('pwd-zip.zip','r') as source:
source.extractall('test-test', pwd = bytes('123','utf-8'))
Ein ZIP-Archive mit Passwortschutz in Python zu erstellen ist leider nicht so einfach, da das Modul zipfile
keine Option unterstützt, um eine passwortgeschütze ZIP zu erstellen. Unter Linux und macOS gibt es allerdings einen Standardbefehl, den man verwenden kann.
zip -P Passwort -r dateiname.zip verzeichnis
Da wir diesen Befehl haben, können wir ihn natürlich auch mit Python ansteuern. Ich habe auch nach anderen Möglichkeiten mit fertigen Paketen gesucht. Allerdings ist die Lösung, auf die immer wieder aufmerksam gemacht wird, die Nutzung dieses Befehls.
Unter Windows könnte man sich zum Beispiel 7zip installieren. Dieses Programm hat auch entsprechende Commands für die CLI.
Um Befehle vom System ausführen zu können, müssen wir das Modul subprocess
verwenden. Darüber können wir Commands mit Argumenten erstellen. Da wir nun eine Funktion schreiben, die nur auf Linux und macOS funktioniert, fragen wir mit dem Modul platform
vorher ab, ob es ein Linux-Betriebssystem oder macOS bzw. Darwin ist. Das ist eine andere Bezeichnung für macOS.
Für Windows haben wir das Programm 7zip entsprechend installiert. Für die Command Line sind wir betriebssystemunabhängig und können das auf allen Betriebssystemen verwenden. Ein Nachteil daran ist, dass 7zip vorher korrekt installiert werden muss.
Danach haben wir eine Abfrage, ob das Passwort gesetzt wurde. Falls nicht, wird der Command ohne den Passwortparameter ausgeführt.
Abschließend prüfen wir, ob unsere ZIP-Datei erstellt wurde, damit wir sichergehen können, dass alles korrekt gelaufen ist.
import platform,subprocess,os
def zip(name,path,pwd = ""):
file = name + '.zip'
if platform.system() in ["Linux","Darwin"]:
if pwd != "":
subprocess.run(["zip", "-P", pwd, '-r', file, path])
else:
subprocess.run(["zip",'-r', file, path])
if platform.system() == "Windows":
if pwd != "":
subprocess.run(['7za',"a",file,path + "/*",'-p' + pwd])
else:
subprocess.run(['7za',"a",file,path + "/*"])
return file in os.listdir('.')
Der Aufruf der Funktion um eine ZIP mit Passwortschutz zu erstellen, könnte zum Beispiel so aussehen:
if zip('test','bilder','123'):
print("ZIP wurde Erstellt.")
else:
print("ZIP wurde nicht Erstellt.")
Du siehst: auch wenn Python keine native Funktion liefert, um ein ZIP-Archive mit Passwort zu erstellen, kannst du dafür auf Shell Commands zugreifen und so dir die Option selbst integrieren.
In diesem Artikel hast du gelesen, dass das Arbeiten mit ZIP-Dateien keinesfalls schwer ist und du es auf jeden Fall beherrschen solltest, wenn du große Datenpakete aus deiner Anwendung exportieren oder importieren willst. Das Arbeiten mit ZIP-Archiven in Python geht mit dem Paket zipfile
definitiv sehr einfach und benötigt nicht viel Aufwand.
Hinterlasse mir gerne einen Kommentar zum Artikel und wie er dir weitergeholfen hat beziehungsweise, was dir helfen würde das Thema besser zu verstehen. Oder hast du einen Fehler entdeckt, den ich korrigieren sollte? Schreibe mir auch dazu gerne ein Feedback!
Hallo Felix, Danke für diesen Beitrag. Deine Funktion createZIP hat mir gerade Arbeit erspart. Sehr gut aufbereitet, schön dargestellt - ich werde meinen Schüler_innen Deine Seite weiter empfehlen.
Viele Grüße Guido