31 Dateisystem 

In diesem Kapitel werden Module besprochen, die Funktionen zum Zugriff auf das Dateisystem bereitstellen. Dazu gehören das Modul os.path zur Arbeit mit Dateipfaden sowie os und shutil für grundlegende Dateisystem-Operationen. Zum Schluss besprechen wir das Modul tempfile, über das temporäre Dateien erzeugt werden können.
Zunächst lernen Sie die Funktionen kennen, die das Modul os für die Arbeit mit dem Dateisystem bereitstellt.
31.1 Zugriff auf das Dateisystem mit os 

Mit den im Folgenden beschriebenen Funktionen können Sie sich wie mit einer Shell oder einem Dateimanager durch das Dateisystem bewegen, Informationen zu Dateien und Ordnern ermitteln, diese umbenennen, löschen oder erstellen. Um die im Folgenden aufgeführten Beispiele ausführen zu können, muss zunächst das Modul os eingebunden werden:
>>> import os
Sie werden oft einen Pfad (engl. path) als Parameter an die beschriebenen Funktionen übergeben können. Dabei unterscheiden wir zwischen absoluten und relativen Pfaden, wobei Letztere sich auf das jeweils aktuelle Arbeitsverzeichnis des laufenden Programms beziehen.
Sofern nichts anderes angemerkt ist, werden Pfade als str- oder bytes-Instanzen übergeben.
Tabelle 31.1 Methoden für den Zugriff auf das Dateisystem
access(path, mode)
Mit access überprüfen Sie, welche Rechte das laufende Python-Programm für den Pfad path hat. Der Parameter mode gibt dabei eine Bit-Maske an, die die zu überprüfenden Rechte enthält.
Folgende Werte können einzeln oder mithilfe des bitweisen ODER zusammengefasst übergeben werden:
Konstante | Bedeutung |
---|---|
F_OK | Prüft, ob der Pfad überhaupt existiert. |
R_OK | Prüft, ob der Pfad gelesen werden darf. |
W_OK | Prüft, ob der Pfad geschrieben werden darf. |
X_OK | Prüft, ob der Pfad ausführbar ist. |
Tabelle 31.2 Wert für den mode-Parameter von os.access
Der Rückgabewert von access ist True, wenn alle für mode übergebenen Werte auf den Pfad zutreffen, und False, wenn mindestens ein Zugriffsrecht für das Programm nicht gilt.
>>> os.access("python.exe", os.F_OK | os.X_OK)
True
Der Aufruf von os.access im obigen Beispiel ergibt, dass die lokale Datei python.exe existiert und ausführbar ist.
chmod(path, mode)
Diese Funktion setzt die Zugriffsrechte der Datei oder des Ordners unter dem übergebenen Pfad. Der Parameter mode ist dabei eine dreistellige Oktalzahl, bei der jede Ziffer die Zugriffsrechte für eine Benutzerklasse angibt. Die erste Ziffer steht für den Besitzer der Datei, die zweite für seine Gruppe und die dritte für alle anderen Benutzer.
Dabei sind die einzelnen Ziffern Summen aus den folgenden drei Werten:
Wert | Beschreibung |
---|---|
1 | ausführen |
2 | schreiben |
4 | lesen |
Tabelle 31.3 Zugriffsflags für os.chmod
Wenn Sie nun beispielsweise den folgenden chmod-Aufruf vornehmen, erteilen Sie dem Besitzer vollen Lese- und Schreibzugriff:
>>> os.chmod("eine_datei", 0o640)
Ausführen kann er die Datei aber trotzdem nicht. Die restlichen Benutzer seiner Gruppe dürfen die Datei lesen, aber nicht verändern, und für alle anderen bleibt aufgrund der fehlenden Leseberechtigung auch der Inhalt der Datei verborgen.
Beachten Sie das führende 0o bei den Zugriffsrechten, das das Literal einer Oktalzahl einleitet.
Diese Funktion ist nur auf Windows- und Unix-Systemen verfügbar.
listdir([path])
Diese Funktion gibt eine Liste zurück, die alle Dateien und Unterordner des Ordners angibt, der mit path übergeben wurde. Diese Liste enthält nicht die speziellen Einträge für das Verzeichnis selbst (".") und für das nächsthöhere Verzeichnis ("..").
Die Elemente der Liste haben den gleichen Typ wie der übergebene path-Parameter, also entweder str oder bytes. Dabei werden auftretende Sonderzeichen mithilfe von UTF-8 codiert.
mkdir(path, [mode])
Diese Funktion legt einen neuen Ordner in dem mit path übergebenen Pfad an. Der optionale Parameter mode gibt dabei eine Bit-Maske an, die die Zugriffsrechte für den neuen Ordner festlegt. Standardmäßig wird für mode die Oktalzahl 0o777 verwendet (siehe zu mode auch chmod).
Ist der angegebene Ordner bereits vorhanden, wird eine os.error-Exception geworfen.
Beachten Sie, dass mkdir nur dann den neuen Ordner erstellen kann, wenn alle übergeordneten Verzeichnisse bereits existieren:
>>> os.mkdir(r"C:\Diesen\Pfad\gibt\es\so\noch\nicht")
[…]
FileNotFoundError: [WinError 3] Das System kann den angegebenen Pfad nicht finden: 'C:\\Diesen\\Pfad\\gibt\\es\\so\\noch\\nicht'
Wenn Sie bei Bedarf die Erzeugung der kompletten Ordnerstruktur wünschen, verwenden Sie makedirs.
makedirs(path, [mode])
Wie mkdir; aber diese Funktion erzeugt im Gegensatz dazu die komplette Verzeichnisstruktur inklusive aller übergeordneten Verzeichnisse.
Damit funktioniert auch folgendes Beispiel:
>>> os.makedirs(r"C:\Diesen\Pfad\gibt\es\so\noch\nicht")
>>>
Wenn der übergebene Ordner schon existiert, wird eine os.error-Exception geworfen.
remove(path)
Diese Funktion entfernt die mit path angegebene Datei aus dem Dateisystem. Übergeben Sie anstelle eines Pfades zu einer Datei einen Pfad zu einem Ordner, wirft remove eine os.error-Exception.
[»] Hinweis
Beachten Sie, dass es auf Windows-Systemen nicht möglich ist, eine Datei zu löschen, die gerade benutzt wird. In diesem Fall wird ebenfalls eine Exception geworfen.
removedirs(path)
Diese Funktion löscht eine ganze Ordnerstruktur, wobei von der tiefsten bis zur höchsten Ebene nacheinander alle Ordner gelöscht werden, sofern diese leer sind. Kann der tiefste Ordner nicht gelöscht werden, wird eine os.error-Exception geworfen. Fehler, die beim Entfernen der Elternverzeichnisse auftreten, werden ignoriert.
Wenn Sie beispielsweise
>>> os.removedirs(r"C:\Irgend\ein\Beispielpfad")
schreiben, wird zuerst versucht, den Ordner C:\Irgend\ein\Beispielpfad zu löschen. Wenn dies erfolgreich war, wird C:\Irgend\ein entfernt und bei Erfolg anschließend C:\Irgend.
Um verschachtelte, nicht leere Verzeichnisse zu löschen, können Sie die Funktion shutil.rmtree verwenden.
rename(src, dst)
Diese Funktion benennt die mit src angegebene Datei oder den Ordner in dst um. Wenn unter dem Pfad dst bereits eine Datei oder ein Ordner existieren, wird os.error geworfen.
[»] Hinweis
Auf Unix-Systemen wird eine bereits unter dem Pfad dst erreichbare Datei ohne Meldung überschrieben, wenn Sie rename aufrufen. Bei bereits existierenden Ordnern wird aber weiterhin eine Exception erzeugt.
Die Methode os.rename funktioniert nur dann, wenn bereits alle übergeordneten Verzeichnisse von dst existieren. Wenn Sie die Erzeugung der nötigen Verzeichnisstruktur wünschen, benutzen Sie stattdessen os.renames.
walk(top, [topdown, onerror])
Eine komfortable Möglichkeit, einen Verzeichnisbaum komplett zu durchlaufen, stellt die Funktion walk bereit. Der Parameter top gibt die Wurzel des zu durchlaufenden Teilbaums an. Die Iteration erfolgt dabei so, dass walk für den Ordner top und für jeden seiner Unterordner ein Tupel mit drei Elementen zurückgibt. Ein solches Tupel kann beispielsweise folgendermaßen aussehen:
('ein\\pfad', ['ordner1'], ['datei1', 'datei2'])
Das erste Element ist der relative Pfad von top zu dem Unterordner, das zweite Element enthält eine Liste mit allen Ordnern, die der aktuelle Unterordner selbst enthält, und das letzte Element speichert alle Dateien des Unterordners.
Um dies genau zu verstehen, betrachten wir einen Beispielverzeichnisbaum:
Abbildung 31.1 Beispielverzeichnisbaum
Wir nehmen an, dass unser aktuelles Arbeitsverzeichnis der Ordner ist, der dem Ordner ich direkt übergeordnet ist.
Dann könnten wir uns einmal die Ausgabe von walk für das Verzeichnis ich ansehen:
>>> for t in os.walk("ich"):
... print(t)
...
('ich', ['freunde', 'eltern'], [])
('ich\\freunde', ['entfernte_freunde'],
['peter', 'christian', 'lucas'])
('ich\\freunde\\entfernte_freunde',[], ['heinz', 'erwin'])
('ich\\eltern', [], ['vater', 'mutter'])
Wie Sie sehen, wird für jeden Ordner ein Tupel erzeugt, das die beschriebenen Informationen enthält. Die doppelten Backslashs "\\" rühren daher, dass das Beispiel auf einem Windows-Rechner ausgeführt wurde und Backslashs innerhalb von String-Literalen als Escape-Sequenz geschrieben werden müssen.
Sie können die in dem Tupel gespeicherten Listen auch bei Bedarf anpassen, um beispielsweise die Reihenfolge zu verändern, in der die Unterverzeichnisse des aktuellen Verzeichnisses besucht werden sollen, oder wenn Sie Änderungen wie das Hinzufügen oder Löschen von Dateien und Ordnern vorgenommen haben.
Mit dem optionalen Parameter topdown, dessen Standardwert True ist, legen Sie fest, wo mit dem Durchlaufen begonnen werden soll. Bei der Standardeinstellung wird in dem Verzeichnis begonnen, das im Verzeichnisbaum der Wurzel am nächsten ist, im Beispiel ich. Wird topdown auf False gesetzt, geht os.walk genau umgekehrt vor und beginnt mit dem am tiefsten verschachtelten Ordner. In unserem Beispielbaum ist das ich/freunde/entfernte_freunde:
>>> for t in os.walk("ich", False):
... print(t)
...
('ich\\freunde\\entfernte_freunde', [], ['heinz', 'erwin'])
('ich\\freunde', ['entfernte_freunde'],
['peter', 'christian', 'lucas'])
('ich\\eltern', [], ['vater', 'mutter'])
('ich', ['freunde', 'eltern'], [])
Zu guter Letzt können Sie mit dem letzten Parameter namens onerror festlegen, wie die Funktion sich verhalten soll, wenn ein Fehler beim Ermitteln des Inhalts eines Verzeichnisses auftritt. Wenn Sie onerror nicht auf dem Standardwert None, der keine Operation vorsieht, belassen wollen, müssen Sie eine Referenz auf eine Funktion, die einen Parameter erwartet, übergeben. Im Fehlerfall wird dann diese Funktion mit einer os.error-Instanz, die den Fehler beschreibt, als Parameter aufgerufen.
[»] Hinweis
Wenn Sie mit einem Betriebssystem arbeiten, das symbolische Verknüpfungen auf Verzeichnisse unterstützt, werden diese beim Durchlaufen der Struktur nicht mit berücksichtigt, um Endlosschleifen zu vermeiden.