Website-Suche

Wie man tar-Archive mit Python erstellt und bearbeitet


Unter Linux und anderen Unix-ähnlichen Betriebssystemen ist tar zweifellos eines der am häufigsten verwendeten Archivierungsprogramme; Es ermöglicht uns, Archive zu erstellen, die oft als "Tarballs" bezeichnet werden, die wir für die Verteilung des Quellcodes oder für Sicherungszwecke verwenden können. In diesem Tutorial werden wir sehen, wie man tar-Archive mit Python liest, erstellt und ändert, indem man das tarfile-Modul verwendet.

In diesem Tutorial lernen Sie:

  • Die Modi, in denen ein tar-Archiv mit dem tarfile-Modul geöffnet werden kann
  • Was sind die TarInfo- und TarFile-Klassen und was stellen sie dar?
  • So listen Sie den Inhalt eines tar-Archivs auf
  • So extrahieren Sie den Inhalt eines tar-Archivs
  • So fügen Sie Dateien zu einem tar-Archiv hinzu
  • Der Name des Tarballs, auf den wir zugreifen möchten
  • Der Modus, in dem es geöffnet werden soll

Der "Modus", der zum Öffnen eines tar-Archivs verwendet wird, hängt von der Aktion ab, die wir ausführen möchten, und von der Art der verwendeten Komprimierung (falls vorhanden). Schauen wir sie uns gemeinsam an.

Öffnen eines Archivs im schreibgeschützten Modus

Wenn wir den Inhalt eines tar-Archivs untersuchen oder extrahieren möchten, können wir einen der folgenden Modi verwenden, um es schreibgeschützt zu öffnen:

ModusBedeutung
'r'Nur-Lese-Modus – der Komprimierungstyp wird automatisch verarbeitet
'r:'Nur-Lese-Modus ohne Komprimierung
'r:gz'Schreibgeschützter Modus – Zip-Komprimierung explizit angegeben
'r:bz2'Schreibgeschützter Modus – bzip-Komprimierung explizit angegeben
'r:xz'Schreibgeschützter Modus – lzma-Komprimierung explizit angegeben

In den meisten Fällen, in denen die Komprimierungsmethode leicht erkannt werden kann, ist der empfohlene Modus 'r'.

Öffnen eines Archivs zum Anhängen von Dateien

Wenn wir Dateien an ein vorhandenes Archiv anhängen möchten, können wir den 'a'-Modus verwenden. Es ist wichtig zu beachten, dass es nur möglich ist, an ein Archiv anzuhängen, wenn es nicht komprimiert ist. Wenn wir versuchen, ein komprimiertes Archiv in diesem Modus zu öffnen, wird eine ValueError-Ausnahme ausgelöst. Wenn wir auf ein nicht vorhandenes Archiv verweisen, wird es im laufenden Betrieb erstellt.

Öffnen eines Archivs zum Schreiben

Wenn wir explizit ein neues Archiv erstellen und zum Schreiben öffnen möchten, können wir einen der folgenden Modi verwenden:

ModusBedeutung
'w'Öffnen Sie das Archiv zum Schreiben – verwenden Sie keine Komprimierung
'w:gz'Öffnen Sie das Archiv zum Schreiben – verwenden Sie die gzip-Komprimierung
'w:bz'Öffnen Sie das Archiv zum Schreiben – verwenden Sie die bzip2-Komprimierung
'w:xz'Öffnen Sie das Archiv zum Schreiben – verwenden Sie die lzma-Komprimierung

Wenn eine vorhandene Archivdatei zum Schreiben geöffnet wird, wird sie abgeschnitten, sodass ihr gesamter Inhalt verworfen wird. Um solche Situationen zu vermeiden, möchten wir möglicherweise das Archiv ausschließlich öffnen, wie im nächsten Abschnitt beschrieben.

Erstellen Sie nur dann ein Archiv, wenn es nicht vorhanden ist

Wenn wir sicherstellen wollen, dass eine vorhandene Datei beim Erstellen eines Archivs nicht überschrieben wird, müssen wir sie ausschließlich öffnen. Wenn wir den 'x'-Modus verwenden und eine Datei mit dem gleichen Namen wie der, den wir für das Archiv angegeben haben, bereits existiert, wird ein FileExistsError ausgelöst. Die Komprimierungsmethoden können wie folgt angegeben werden:

ModusBedeutung
'x'Erstellen Sie das Archiv ohne Komprimierung, wenn es nicht vorhanden ist
'x:gz'Erstellen Sie das Archiv nur dann mit gzip-Komprimierung, wenn es nicht vorhanden ist
'x:bz2'Erstellen Sie das Archiv mit bzip2-Komprimierung nur, wenn es nicht existiert
'x:xz'Erstellen Sie das Archiv nur dann mit lzma-Komprimierung, wenn es nicht vorhanden ist

Arbeiten mit Archiven

Es gibt zwei Klassen, die vom tarfile-Modul bereitgestellt werden und für die Interaktion mit tar-Archiven und deren Inhalten verwendet werden: TarFile und TarInfo. Ersteres wird verwendet, um ein tar-Archiv in seiner Gesamtheit darzustellen und kann als Kontextmanager mit der Python with-Anweisung verwendet werden, letzteres wird verwendet, um ein Archivmitglied darzustellen, und enthält verschiedene Informationen darüber. In einem ersten Schritt konzentrieren wir uns auf einige der am häufigsten verwendeten Methoden der TarFile-Klasse: Wir können sie verwenden, um gängige Operationen in tar-Archiven durchzuführen.

Abrufen einer Liste der Archivmitglieder

Um eine Liste der Archivmitglieder abzurufen, können wir die getmembers-Methode eines TarFile-Objekts verwenden. Diese Methode gibt eine Liste von TarInfo-Objekten zurück, eines für jedes Archivmitglied. Hier ist ein Beispiel für die Verwendung mit einem komprimierten Dummy-Archiv, das zwei Dateien enthält:

>>> with tarfile.open('archive.tar.gz', 'r') as archive:
...     archive.getmembers()
...
[<TarInfo 'file1.txt' at 0x7f58dab50d00>, <TarInfo 'file2.txt' at 0x7f58dab50ac0>]

Wie wir später sehen werden, können wir über die entsprechenden Eigenschaften und Methoden des TarInfo-Objekts auf einige der Attribute einer archivierten Datei zugreifen, wie z. B. deren Eigentum und Änderungszeit.

Anzeigen des Inhalts eines tar-Archivs

Wenn wir nur den Inhalt eines tar-Archivs anzeigen möchten, können wir es im Lesemodus öffnen und die list-Methode der Tarfile-Klasse verwenden.

>>> with tarfile.open('archive.tar.gz', 'r') as archive:
...     archive.list()
...
?rw-r--r-- egdoc/egdoc          0 2020-05-16 15:45:45 file1.txt
?rw-r--r-- egdoc/egdoc          0 2020-05-16 15:45:45 file2.txt

Wie Sie sehen können, wird die Liste der im Archiv enthaltenen Dateien als Ausgabe angezeigt. Die list-Methode akzeptiert einen Positionsparameter, verbose, der standardmäßig True ist. Wenn wir den Wert in False ändern, werden nur die Dateinamen in der Ausgabe angezeigt, ohne zusätzliche Informationen.

Die Methode akzeptiert auch einen optionalen benannten Parameter, members. Wenn es verwendet wird, muss das angegebene Argument eine Teilmenge der Liste der TarInfo-Objekte sein, die von der getmembers-Methode zurückgegeben werden. Es werden nur Informationen zu den angegebenen Dateien angezeigt, wenn dieser Parameter verwendet wird und ein korrekter Wert angegeben wird.

Extrahieren aller Mitglieder aus dem tar-Archiv

Eine weitere sehr häufige Operation, die wir für ein tar-Archiv durchführen möchten, ist das Extrahieren des gesamten Inhalts. Um eine solche Operation durchzuführen, können wir die Methode extractalldes entsprechenden TarFile-Objekts verwenden. Hier ist, was wir schreiben würden:

>>> with tarfile.open('archive.tar.gz', 'r') as archive:
...     archive.extractall()

Der erste Parameter, der von der Methode akzeptiert wird, ist path: Er wird verwendet, um anzugeben, wohin die Mitglieder des Archivs extrahiert werden sollen. Der Standardwert ist '.', sodass die Member im aktuellen Arbeitsverzeichnis extrahiert werden.

Der zweite Parameter, members, kann verwendet werden, um eine Teilmenge von Elementen anzugeben, die aus dem Archiv extrahiert werden sollen, und wie im Fall der list-Methode sollte es sich um eine Teilmenge der Liste handeln, die von der getmembers-Methode zurückgegeben wird.

Die extractall-Methode verfügt auch über einen benannten Parameter, numeric_owner. Es ist standardmäßig False: Wenn wir es auf True ändern, werden numerische uid und gid verwendet, um den Besitz der extrahierten Dateien anstelle von Benutzer- und Gruppennamen festzulegen.

Extrahieren von nur einem Element aus dem Archiv

Was ist, wenn wir nur eine einzige Datei aus dem Archiv extrahieren möchten? In diesem Fall möchten wir die Methode extract verwenden und die Datei, die extrahiert werden soll, anhand ihres Namens (oder als TarFile-Objekt) referenzieren. Um beispielsweise nur die file1.txt Datei aus dem Tarball zu extrahieren, würden wir Folgendes ausführen:

>>> with tarfile.open('archive.tar.gz', 'r') as archive:
...     archive.extract('file1.txt')

Einfach, nicht wahr? Die Datei wird standardmäßig im aktuellen Arbeitsverzeichnis extrahiert, aber mit dem zweiten Parameter, der von der Methode akzeptiert wird, kann eine andere Position angegeben werden: path.

Normalerweise werden die Attribute, die die Datei im Archiv hat, gesetzt, wenn sie auf dem Dateisystem extrahiert wird. Um dieses Verhalten zu vermeiden, können wir den dritten Parameter der Funktion, set_attrs, auf False setzen.

Die Methode akzeptiert auch den numeric_owner Parameter: Die Verwendung ist die gleiche, die wir im Kontext der extractall-Methode gesehen haben.

Extrahieren eines Archivelements als dateiähnliches Objekt

Wir haben gesehen, wie wir mit den Methoden extractall und extract ein oder mehrere Mitglieder des tar-Archivs in das Dateisystem extrahieren können. Das tarfile-Modul bietet eine weitere Extraktionsmethode: extractfile. Wenn diese Methode verwendet wird, wird die angegebene Datei nicht in das Dateisystem extrahiert. Stattdessen wird ein schreibgeschütztes dateiähnliches Objekt zurückgegeben, das es darstellt:

>>> with tarfile.open('archive.tar.gz', 'r') as archive:
...     fileobj = archive.extractfile('file1.txt')
...     fileobj.writable()
...     fileobj.read()
...
False
b'hello\nworld\n'

Hinzufügen von Dateien zu einem Archiv

Bisher haben wir gesehen, wie man Informationen über ein Archiv und seine Mitglieder erhält und welche verschiedenen Methoden wir verwenden können, um seinen Inhalt zu extrahieren. Jetzt ist es an der Zeit zu sehen, wie wir neue Mitglieder hinzufügen können.

Der einfachste Weg, eine Datei zu einem Archiv hinzuzufügen, ist die Verwendung der add-Methode. Wir verweisen auf die Datei, die in das Archiv aufgenommen werden soll, mit dem Namen, der der erste Parameter ist, der von der Methode akzeptiert wird. Die Datei wird unter ihrem ursprünglichen Namen archiviert, es sei denn, wir geben einen anderen Namen mit dem zweiten Positionsparameter an: arcname. Angenommen, wir möchten das file1.txt zu einem neuen Archiv hinzufügen, es aber als archived_file1.txt speichern. Wir würden schreiben:

>>> with tarfile.open('new_archive.tar.gz', 'w') as archive:
...     archive.add('file1.txt', 'archived_file1.txt')
...     archive.list()
...
-rw-r--r-- egdoc/egdoc         12 2020-05-16 17:49:44 archived_file1.txt

Im obigen Beispiel haben wir ein neues unkomprimiertes Archiv im 'w'-Modus erstellt und das file1.txt als archive_file1.txt hinzugefügt, wie Sie an der Ausgabe von list() sehen können.

Verzeichnisse können auf die gleiche Weise archiviert werden: Standardmäßig werden sie rekursiv hinzugefügt, also zusammen mit ihrem Inhalt. Dieses Verhalten kann geändert werden, indem der dritte von der add-Methode akzeptierte Positionsparameter, rekursiv, auf False festgelegt wird.

Was ist, wenn wir einen Filter anwenden möchten, so dass nur bestimmte Dateien in das Archiv aufgenommen werden? Zu diesem Zweck können wir den optionalen Filter named parameter verwenden. Der Wert, der an diesen Parameter übergeben wird, muss eine Funktion sein, die ein TarInfo-Objekt als Argument annimmt und dieses Objekt zurückgibt, wenn es in das Archiv aufgenommen werden muss, oder Keine, wenn es ausgeschlossen werden muss. Sehen wir uns ein Beispiel an. Angenommen, wir haben drei Dateien in unserem aktuellen Arbeitsverzeichnis: file1.txt, file2.txt und file1.md. Wir möchten nur die Dateien mit der Erweiterung .txt zum Archiv hinzufügen. Hier ist, was wir schreiben könnten:

>>> import os
>>> import tarfile
>>> with tarfile.open('new_archive.tar.gz', 'w') as archive:
...     for i in os.listdir():
...         archive.add(i, filter=lambda x: x if x.name.endswith('.txt') else None)
...     archive.list()
...
-rw-r--r-- egdoc/egdoc          0 2020-05-16 18:26:20 file2.txt
-rw-r--r-- egdoc/egdoc          0 2020-05-16 18:22:13 file1.txt

Im obigen Beispiel haben wir die os.listdir-Methode verwendet, um eine Liste der Dateien zu erhalten, die im aktuellen Arbeitsverzeichnis enthalten sind. Beim Durchlaufen dieser Liste haben wir die add-Methode verwendet, um jede Datei zum Archiv hinzuzufügen. Wir haben eine Funktion als Argument des Filterparameters übergeben, in diesem Fall eine anonyme, ein Lambda. Die Funktion nimmt das Tarfile-Objekt als Argument (x) und gibt es zurück, wenn sein Name (name ist eine der Eigenschaften des TarInfo-Objekts) mit ".txt " endet. Ist dies nicht der Fall, gibt die Funktion None zurück, sodass die Datei nicht archiviert wird.

Das TarInfo-Objekt

Wir haben bereits gelernt, dass das TarInfo-Objekt ein tar-Archivmitglied darstellt: Es speichert die Attribute der referenzierten Datei und stellt einige Methoden bereit, die uns helfen können, den Dateityp selbst zu identifizieren. Das TarInfo-Objekt enthält nicht die eigentlichen Dateidaten. Einige der Attribute des TarInfo-Objekts sind:

  • name (Name der Datei)
  • size (Dateigröße)
  • mtime (Zeit für Dateiänderungen)
  • UID (die Benutzer-ID des Dateieigentümers)
  • gid (die ID der Dateigruppe)
  • uname (der Benutzername des Dateieigentümers)
  • gname (der Name der Dateigruppe)

Das Objekt verfügt auch über einige sehr nützliche Methoden, hier sind einige davon:

  • isfile() – Gibt True zurück, wenn es sich um eine reguläre Datei handelt, andernfalls False
  • isdir() – Gibt True zurück, wenn es sich bei der Datei um ein Verzeichnis handelt, andernfalls False
  • issym() – Gibt True zurück, wenn es sich bei der Datei um einen symbolischen Link handelt, andernfalls False
  • isblk() – Gibt True zurück, wenn es sich bei der Datei um ein Blockgerät handelt, sonst False

Schlüsse

In diesem Tutorial haben wir die grundlegende Verwendung des Python-Moduls tarfile kennengelernt und gesehen, wie wir es verwenden können, um mit tar-Archiven zu arbeiten. Wir haben die verschiedenen Betriebsmodi gesehen, was die Klassen TarFile und TarInfo darstellen und einige der am häufigsten verwendeten Methoden, um den Inhalt eines Archivs aufzulisten, neue Dateien hinzuzufügen oder sie zu extrahieren. Für tiefergehende Kenntnisse des tarfile-Moduls werfen Sie bitte einen Blick in die offizielle Dokumentation des Moduls

Verwandte Artikel: