»Aber ich kann dir nur die Tür zeigen, durchgehen musst du ganz allein. Tank, das Sprungprogramm!« – Morpheus in Matrix
17 Schnittstelle zum Betriebssystem
Um Ihre Programme mit dem Betriebssystem interagieren zu lassen, auf dem sie ausgeführt werden, benötigen Sie Zugriff auf dessen Funktionen. Ein Problem dabei ist, dass sich die verschiedenen Betriebssysteme teilweise sehr stark in ihrem Funktionsumfang und in der Art unterscheiden, wie die vorhandenen Operationen zu benutzen sind. Python wurde aber von Grund auf als plattformübergreifende Sprache konzipiert. Um auch Programme, die auf Funktionen des Betriebssystems zurückgreifen müssen, auf möglichst vielen Plattformen ohne Änderungen ausführen zu können, hat man eine Schnittstelle geschaffen, die einheitlichen Zugriff auf Betriebssystemfunktionen bietet. Im Klartext bedeutet dies, dass Sie durch die Benutzung dieser einheitlichen Schnittstelle Programme schreiben können, die plattformunabhängig bleiben, selbst wenn sie auf Betriebssystemfunktionen zurückgreifen.
Die Schnittstelle wird durch das Modul os implementiert, mit dem wir uns im weiteren Verlauf des Kapitels beschäftigen werden.
17.1 Funktionen des Betriebssystems – os 

Mit dem os-Modul können Sie auf mehrere Klassen von Operationen zugreifen. Da die gebotenen Funktionen sehr umfangreich sind und zu einem großen Teil nur selten gebraucht werden, beschränken wir uns hier auf eine Teilmenge, die sich in folgende Kategorien einteilen lässt:
- Zugriff auf den Prozess, in dem unser Python-Programm läuft, und auf andere Prozesse
- Zugriff auf das Dateisystem
- Informationen über das Betriebssystem
Außerdem stellt das Submodul os.path nützliche Operationen für die Manipulation und Verarbeitung von Pfadnamen bereit.
Das Modul os hat eine eigene Exception-Klasse namens os.error. Immer wenn Sie Fehler innerhalb dieses Moduls abfangen möchten, können Sie dies über os.error tun. Ein alternativer Name für die Fehlerklasse ist OSError.
Wir werden nun eine Auswahl von Funktionen der drei Kategorien besprechen.
17.1.1 Zugriff auf den eigenen Prozess und andere Prozesse 

os.environ
Diese Konstante enthält ein Dictionary, das die Umgebungsvariablen speichert, die für unser Programm vom Betriebssystem bereitgestellt wurden. Beispielsweise lässt sich auf vielen Plattformen mit os.environ['HOME'] der Pfad des Ordners für die Dateien des aktiven Benutzers ermitteln. Die folgenden Beispiele zeigen den Wert von os.environ['HOME'] auf einem Windows- und einem Linux-Rechner:
>>> print os.environ['HOME'] C:\Dokumente und Einstellungen\revelation
>>> print os.environ['HOME'] /home/revelation
Sie können die Werte des os.environ-Dictionarys auch verändern, was allerdings auf bestimmten Plattformen zu Problemen führen kann und deshalb mit Vorsicht zu genießen ist.
os.getpid()
Jeder laufende Prozess hat eine eindeutige Identifikationsnummer, die sich mit os.getpid() ermitteln lässt:
>>> os.getpid() 1360
Diese Funktion ist nur unter Windows- und Unix-Systemen verfügbar.
os.system(cmd)
Mit os.system können Sie beliebige Kommandos des Betriebssystems ausführen, so als ob Sie es in einer echten Konsole tun würden. Beispielsweise lassen wir uns mit folgendem Beispiel einen neuen Ordner mit dem Namen test_ordner über das »mkdir«-Kommando anlegen:
>>> os.system("mkdir test_ordner")
0Der Rückgabewert von os.system ist der Statuscode, mit dem das aufgerufene Programm beendet wurde, in diesem Fall 0.
Ein Problem der os.system-Funktion ist, dass die Ausgabe des aufgerufenen Programms nicht ohne Weiteres ermittelt werden kann. Für solche Zwecke eignet sich die folgende os.popen-Funktion.
os.popen(command[, mode[, bufsize]])
Mit der Funktion os.popen können beliebige Befehle wie auf einer Kommandozeile des Betriebssystems ausgeführt werden. Die Funktion gibt ein Dateiobjekt zurück, mit dem auf die Ausgabe des ausgeführten Programms zugegriffen werden kann. Mit dem Parameter mode wird wie bei der Built-in Function open angegeben, ob das Dateiobjekt lesend ("r") oder schreibend ("w") geöffnet werden soll. Bei schreibendem Zugriff können auch Daten an das laufende Programm übergeben werden.
Im folgenden Beispiel nutzen wir das Windows-Kommando »dir«, um eine Liste der Dateien und Ordner unter C:\ zu erzeugen:
>>> ausgabe = os.popen("dir /B C:\\") >>> dateien = [zeile.strip() for zeile in ausgabe] >>> dateien ['AUTOEXEC.BAT', 'CONFIG.SYS', 'Dokumente und Einstellungen', 'Programme', 'Python25', 'WINDOWS']
Die genaue Bedeutung von mode und bufsize können Sie in Abschnitt 9.3, »Dateien«, nachlesen.
17.1.2 Zugriff auf das Dateisystem 

Mit den nachfolgend beschriebenen Funktionen können Sie sich wie mit einer Shell durch das Dateisystem bewegen, Informationen zu Dateien und Ordnern ermitteln, diese umbenennen, löschen oder erstellen.
Sie werden oft einen sogenannten 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 aktuelle Arbeitsverzeichnis beziehen.
Sofern nichts anderes angemerkt ist, werden Pfade als str- oder unicode-Instanzen übergeben.
os.access(path, mode)
Mit os.access kann überprüft werden, welche Rechte das laufende Python-Programm für den Pfad path hat. Der Parameter mode gibt dabei eine Bitmaske an, die die zu überprüfenden Rechte enthält.
Folgende Werte können einzeln oder mithilfe des bitweisen ODERs zusammengefasst übergeben werden:
| Konstante | Bedeutung |
|
os.F_OK |
Prüft, ob der Pfad überhaupt exisitert. |
|
os.R_OK |
Prüft, ob der Pfad gelesen werden darf. |
|
os.W_OK |
Prüft, ob der Pfad geschrieben werden darf. |
|
os.X_OK |
Prüft, ob der Pfad ausführbar ist. |
Der Rückgabewert von os.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.chdir(path)
Setzt das aktuelle Arbeitsverzeichnis auf den mit path übergebenen Pfad.
os.getcwd()
Gibt einen String zurück, der den Pfad des aktuellen Arbeitsverzeichnisses (Current Working Directory) enthält.
os.getcwdu()
Wie os.getcwd, gibt aber eine unicode-Instanz zurück.
os.chmod(path, mode)
Setzt die Zugriffsrechte der Datei oder des Ordners unter dem übergebenen Pfad. 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 |
Wenn Sie nun beispielsweise den nachstehenden os.chmod-Aufruf durchführen, erteilen Sie dem Besitzer vollen Lese- und Schreibzugriff:
>>> os.chmod("eine_datei", 0640)Ausführen kann er die Datei aber trotzdem nicht. Die restlichen Benutzer seiner Gruppe dürfen die Datei auslesen, aber nicht verändern, und für alle anderen bleibt aufgrund der fehlenden Leseberechtigung auch der Inhalt der Datei verborgen.
Beachten Sie die führende 0 bei den Zugriffsrechten, die das Literal einer Oktalzahl einleitet.
Diese Funktion ist nur unter Windows- und Unix-Systemen verfügbar.
os.listdir(path)
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 das nächsthöhere Verzeichnis ("..").
Die Elemente der Liste haben den gleichen Typ wie der übergebene path-Parameter, also entweder str oder unicode.
os.mkdir(path[, mode])
Legt einen neuen Ordner in dem mit path übergebenen Pfad an. Der optionale Parameter mode gibt dabei eine Bitmaske an, die die Zugriffsrechte für den neuen Ordner festlegt. Standardmäßig wird für mode die Oktalzahl 0777 verwendet (siehe zu mode auch os.chmod).
Ist der angegebene Ordner bereits vorhanden, wird eine os.error-Exception geworfen.
Beachten Sie, dass os.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") […] WindowsError: [Error 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 os.makedirs.
os.makedirs(path[, mode])
Wie os.mkdir; erzeugt aber 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.
os.remove(path)
Entfernt die mit path angegebene Datei aus dem Dateisystem. Wird statt eines Pfads zu einer Datei ein Pfad zu einem Ordner übergeben, wirft os.remove eine os.error-Exception (siehe dazu os.rmdir).
Beachten Sie bitte, dass es unter Windows-Systemen nicht möglich ist, eine Datei zu löschen, die gerade benutzt wird. In diesem Fall wird ebenfalls eine Exception geworfen.
os.removedirs(path)
Löscht eine ganze Ordnerstruktur. Dabei löscht es von der tiefsten bis zur höchsten Ebene nacheinander alle Ordner, 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.
os.rename(src, dst)
Benennt die mit src angegebene Datei oder den Ordner in dst um. Wenn unter dem Pfad dst bereits eine Datei oder ein Ordner existiert, wird os.error geworfen.
| Achtung |
| Auf Unix-Systemen wird eine bereits unter dem Pfad dst erreichbare Datei ohne Meldung überschrieben, wenn Sie os.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.
os.renames(src, dst)
Wie os.rename, legt aber bei Bedarf die Verzeichnisstruktur des Zielpfads an. Außerdem wird nach dem Benennungsvorgang versucht, den src-Pfad mittels os.removedirs von leeren Ordnern zu reinigen.
os.rmdir(path)
Entfernt den übergebenen Ordner aus dem Dateisystem oder wirft os.error, wenn der Ordner nicht existiert.
os.tmpfile()
Legt eine temporäre Datei an und gibt ein geöffnetes Dateiobjekt für sie zurück. Nach dem Schließen der Datei wird sie automatisch gelöscht.
Diese Funktion ist äußerst praktisch, wenn Sie kurz Daten auf die Festplatte auslagern möchten.
os.walk(top[, topdown=True[, onerror=None]])
Eine sehr komfortable Möglichkeit, einen Verzeichnisbaum komplett zu durchlaufen, stellt die Funktion os.walk bereit. Der Parameter top gibt dabei die Wurzel des zu durchlaufenden Teilbaums an. Die Iteration geht dabei so vonstatten, dass os.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 dabei der Pfad zu dem Unterordner inklusive des Pfads relativ zu top, 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 17.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 os.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 agiusgefü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, kann man festlegen, wo mit dem Durchlaufen begonnen werden soll. Bei der Standardeinstellung wird in dem Verzeichnis begonnen, das im Verzeichnisbaum der Wurzel am nächsten steht, 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 kann mit dem letzten Parameter namens onerror festgelegt werden, 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.
| Wichtig |
| Wenn Sie mit einem Betriebssystem arbeiten, das symbolische Links auf Verzeichnisse unterstützt, werden diese beim Durchlaufen der Struktur nicht mit berücksichtigt. Dieses Verhalten ist deshalb sinnvoll, weil sonst schwierig zu vermeidende Endlosschleifen entstehen können. |
| Achtung |
| Wenn Sie wie in unserem Beispiel einen relativen Pfadnamen angeben, dürfen Sie das aktuelle Arbeitsverzeichnis nicht während des Durchlaufens mittels os.walk verändern. |
| Wenn Sie es dennoch tun, kann dies zu nicht definiertem Verhalten führen. |





bestellen





