Python os- und sys-Module
Python os und sys Module meistern: Dateisystem navigieren, Umgebungsvariablen verwalten, Interpreter-Zustand prüfen und Kommandozeilenargumente verarbeiten.
Die Module os und sys gehören zu den wichtigsten Werkzeugen der Python-Standardbibliothek. os verbindet Python mit dem zugrunde liegenden Betriebssystem — es ermöglicht die Navigation in Verzeichnissen, das Lesen und Setzen von Umgebungsvariablen sowie die Manipulation von Dateien und Pfaden. sys verbindet Python mit dem Interpreter selbst — es stellt die Argumentliste, den Modulsuchpfad und Hooks zur Steuerung des Interpreter-Exits bereit. Zusammen decken sie fast alles ab, was ein Skript für die Interaktion mit seiner Ausführungsumgebung benötigt.
Das os-Modul
Importieren Sie os am Anfang Ihres Skripts:
import osEine Installation ist nicht erforderlich; das Modul ist in jeder Python-Distribution enthalten.
Mit Verzeichnissen arbeiten
Aktuelles Arbeitsverzeichnis abrufen und wechseln
os.getcwd() gibt den absoluten Pfad des Verzeichnisses zurück, in dem Ihr Skript ausgeführt wird. os.chdir() wechselt das aktuelle Verzeichnis.
import os
# Print the current directory
print(os.getcwd())
# Example output: /Users/alice/projects
# Change to a different directory
os.chdir("/tmp")
print(os.getcwd())
# Output: /tmpVerzeichnisinhalt auflisten
os.listdir(path) gibt eine Liste aller Einträge (Dateien und Unterverzeichnisse) in path zurück. Es durchsucht keine Unterverzeichnisse rekursiv.
import os
entries = os.listdir(".") # "." means current directory
for entry in sorted(entries):
print(entry)Um Dateien von Verzeichnissen zu unterscheiden, verwenden Sie os.path.isfile() und os.path.isdir():
import os
for entry in os.listdir("."):
if os.path.isdir(entry):
print(f"[DIR] {entry}")
else:
print(f"[FILE] {entry}")Verzeichnisse erstellen und entfernen
import os
# Create a single directory
os.mkdir("reports")
# Create nested directories in one call
os.makedirs("data/2024/january", exist_ok=True)
# exist_ok=True prevents an error if the directory already exists
# Remove an empty directory
os.rmdir("reports")
# Remove a full directory tree
import shutil
shutil.rmtree("data")Der Parameter exist_ok=True in os.makedirs() ist sehr nützlich in Skripten, die möglicherweise mehrfach ausgeführt werden — ohne ihn löst ein zweiter Durchlauf einen FileExistsError aus.
Einen Verzeichnisbaum durchlaufen
os.walk(top) erzeugt für jedes Verzeichnis im Baum mit Wurzel top ein Drei-Tupel (dirpath, dirnames, filenames). Es ist die Standardmethode, um eine Ordnerstruktur rekursiv zu durchsuchen.
import os
for dirpath, dirnames, filenames in os.walk("project"):
level = dirpath.count(os.sep)
indent = " " * level
print(f"{indent}{os.path.basename(dirpath)}/")
for filename in filenames:
print(f"{indent} {filename}")Mit Dateipfaden arbeiten
Das Untermodul os.path von Python enthält portable Pfadmanipulations-Hilfsfunktionen, die unter Windows, macOS und Linux korrekt funktionieren.
Pfadkomponenten zusammenführen
os.path.join() kombiniert Teile eines Pfades mit dem für das aktuelle Betriebssystem korrekten Trennzeichen.
import os
base = "/home/alice"
project = "myapp"
filename = "config.json"
full_path = os.path.join(base, project, filename)
print(full_path)
# Output: /home/alice/myapp/config.jsonBauen Sie Pfade niemals mit String-Verkettung wie base + "/" + filename auf — das funktioniert unter Windows nicht. Verwenden Sie immer os.path.join().
Einen Pfad aufteilen
import os
path = "/home/alice/myapp/config.json"
print(os.path.dirname(path)) # /home/alice/myapp
print(os.path.basename(path)) # config.json
print(os.path.split(path)) # ('/home/alice/myapp', 'config.json')
print(os.path.splitext(path)) # ('/home/alice/myapp/config', '.json')os.path.splitext() ist praktisch, wenn Sie eine Dateiendung entfernen oder ändern möchten.
Prüfen, ob ein Pfad existiert
import os
print(os.path.exists("/tmp")) # True (usually)
print(os.path.isfile("/tmp")) # False — it is a directory
print(os.path.isdir("/tmp")) # True
print(os.path.isabs("/tmp")) # True — it is an absolute pathDen absoluten Pfad ermitteln
os.path.abspath() löst relative Pfade gegen das aktuelle Arbeitsverzeichnis auf:
import os
print(os.path.abspath("config.json"))
# Example output: /home/alice/myapp/config.jsonDies ist nützlich, wenn Sie einen Pfad speichern oder protokollieren möchten, der auch dann gültig bleibt, wenn sich das Arbeitsverzeichnis später ändert.
Die __file__-Variable und skriptrelative Pfade
Ein häufiger Stolperstein: Ein Skript, das "data.csv" öffnet, funktioniert, wenn es aus seinem eigenen Verzeichnis gestartet wird, schlägt aber aus einem anderen Verzeichnis fehl. Die Lösung besteht darin, den Pfad relativ zur Skriptdatei selbst zu konstruieren:
import os
# Directory that contains *this* script
HERE = os.path.dirname(os.path.abspath(__file__))
data_file = os.path.join(HERE, "data.csv")
with open(data_file, encoding="utf-8") as f:
content = f.read()Diese Technik macht Skripte portabel, unabhängig davon, aus welchem Verzeichnis sie gestartet werden.
Umgebungsvariablen
Umgebungsvariablen speichern Konfigurationen außerhalb des Quellcodes — Datenbank-URLs, API-Schlüssel, Feature-Flags und so weiter. Die Zuordnung os.environ bietet Lese- und Schreibzugriff auf die Umgebung des aktuellen Prozesses.
Eine Umgebungsvariable lesen
import os
# Returns the value or None if not set
home = os.environ.get("HOME")
print(home)
# Example output: /home/alice
# Raise KeyError if not set (useful to fail fast on missing config)
path = os.environ["PATH"]Bevorzugen Sie os.environ.get(key) gegenüber os.environ[key], es sei denn, die Variable ist zwingend erforderlich und das Programm soll ohne sie abstürzen.
Mit einem Standardwert lesen
import os
debug = os.environ.get("DEBUG", "false")
port = int(os.environ.get("PORT", "8080"))
print(f"debug={debug}, port={port}")
# Output: debug=false, port=8080Umgebungsvariablen setzen und löschen
import os
# Set a variable — affects only the current process and its children
os.environ["MY_APP_ENV"] = "production"
# Remove a variable
os.environ.pop("MY_APP_ENV", None) # None prevents KeyError if not presentDas Setzen von os.environ-Werten bleibt nicht nach dem Prozessende erhalten. Um permanente Umgebungsvariablen zu setzen, ändern Sie Ihr Shell-Profil (~/.bashrc, ~/.zshrc) oder verwenden Sie eine .env-Datei, die von einer Bibliothek wie python-dotenv geladen wird.
Alle Umgebungsvariablen auflisten
import os
for key, value in sorted(os.environ.items()):
print(f"{key}={value}")Shell-Befehle mit os.system() und subprocess ausführen
os.system(command) führt einen Shell-Befehl aus und gibt dessen Exit-Code zurück, bietet jedoch keine Möglichkeit, die Ausgabe zu erfassen. Für alles, was über einen schnellen Fire-and-Forget-Aufruf hinausgeht, verwenden Sie stattdessen das Modul subprocess.
import os
import subprocess
# Quick way — exit code only
exit_code = os.system("echo hello")
print("exit code:", exit_code) # 0 means success
# Better way — capture output
result = subprocess.run(
["echo", "hello"],
capture_output=True,
text=True,
)
print(result.stdout.strip()) # hellosubprocess.run() ist mächtiger und sicherer als os.system(), da es den Shell-Interpreter umgeht und es Ihnen ermöglicht, stdout, stderr und den Rückgabecode als Python-Objekte zu erfassen.
Nützliche os-Hilfsfunktionen
| Funktion | Beschreibung |
|---|---|
os.getcwd() | Aktuelles Arbeitsverzeichnis |
os.chdir(path) | Arbeitsverzeichnis wechseln |
os.listdir(path) | Verzeichniseinträge auflisten |
os.mkdir(path) | Ein Verzeichnis erstellen |
os.makedirs(path, exist_ok=True) | Verschachtelte Verzeichnisse erstellen |
os.rmdir(path) | Ein leeres Verzeichnis entfernen |
os.remove(path) | Eine Datei löschen |
os.rename(src, dst) | Eine Datei umbenennen / verschieben |
os.walk(top) | Einen Verzeichnisbaum rekursiv durchlaufen |
os.environ | Zuordnung der Umgebungsvariablen |
os.getpid() | Aktuelle Prozess-ID |
os.cpu_count() | Anzahl der logischen CPU-Kerne |
Das sys-Modul
sys stellt Informationen über den Python-Interpreter bereit und bietet Hooks zur Steuerung seines Verhaltens.
import sysKommandozeilenargumente mit sys.argv
sys.argv ist eine Liste von Strings. sys.argv[0] ist der Skriptname; die nachfolgenden Elemente sind die auf der Kommandozeile übergebenen Argumente.
Angenommen, Sie speichern dies als greet.py und führen python greet.py Alice 42 aus:
import sys
script_name = sys.argv[0] # 'greet.py'
name = sys.argv[1] # 'Alice'
age = sys.argv[2] # '42' — always a string
print(f"Hello, {name}! You are {age} years old.")
# Output: Hello, Alice! You are 42 years old.Validieren Sie sys.argv immer, bevor Sie auf Indizes zugreifen — ein IndexError lässt das Skript abstürzen, wenn der Benutzer ein Argument vergisst:
import sys
if len(sys.argv) != 3:
print(f"Usage: python {sys.argv[0]} <name> <age>")
sys.exit(1)
name = sys.argv[1]
age = sys.argv[2]
print(f"Hello, {name}! You are {age} years old.")Für komplexes Argument-Parsing bevorzugen Sie das Modul argparse aus der Standardbibliothek — es generiert automatisch --help-Ausgaben.
Den Interpreter mit sys.exit() beenden
sys.exit(code) löst SystemExit aus und beendet den Interpreter. Konventionsgemäß bedeutet Exit-Code 0 Erfolg; jeder Wert ungleich null signalisiert einen Fehler.
import sys
answer = input("Continue? (y/n): ")
if answer.lower() != "y":
print("Goodbye!")
sys.exit(0)
print("Continuing...")Sie können SystemExit in einem try/except-Block abfangen, wenn Sie vor dem Programmende noch Bereinigungen durchführen möchten, aber normalerweise übernimmt die with-Anweisung (für Datei-Handles, Netzwerkverbindungen usw.) die Bereinigung automatisch.
Python-Versionsinformationen
import sys
print(sys.version)
# Example: 3.10.15 (main, ...) [GCC 11.4.0]
print(sys.version_info)
# sys.version_info(major=3, minor=10, micro=15, ...)
# Guard against running on an unsupported Python version
if sys.version_info < (3, 8):
sys.exit("This script requires Python 3.8 or later.")sys.version_info ist ein benanntes Tupel, das Sie direkt mit einem Tupel aus ganzen Zahlen vergleichen können.
Der Modulsuchpfad (sys.path)
Wenn Sie import mymodule schreiben, durchsucht Python jedes Verzeichnis in sys.path der Reihe nach, bis es eine passende Datei findet. Die Liste beginnt mit dem Verzeichnis des Skripts (oder einem leeren string für interaktive Sitzungen), gefolgt von PYTHONPATH-Einträgen und dann der Standardbibliothek sowie site-packages.
import sys
for p in sys.path:
print(p)Sie können sys.path zur Laufzeit erweitern, um Module aus nicht standardmäßigen Speicherorten zu importieren:
import sys
import os
# Add a sibling directory to the search path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "libs"))
import mymodule # now found in ./libs/mymodule.pyDas Modifizieren von sys.path ist eine schnelle Lösung für die lokale Entwicklung, aber für verteilbare Pakete verwenden Sie stattdessen pip und eine ordnungsgemäße pyproject.toml.
Standardströme
sys.stdin, sys.stdout und sys.stderr sind dateiähnliche Objekte, die mit den drei Standardströmen verbunden sind. Sie können sie umleiten, um Ausgaben zu erfassen oder zu unterdrücken.
import sys
# Write to stdout (same as print, but more explicit)
sys.stdout.write("Hello, stdout\n")
# Write to stderr (errors and diagnostics)
sys.stderr.write("Warning: something looks off\n")Ein häufiges Muster in Skripten ist die Umleitung von sys.stdout in eine Datei, um alle print()-Ausgaben zu erfassen:
import sys
with open("output.log", "w", encoding="utf-8") as log:
original_stdout = sys.stdout
sys.stdout = log
print("This goes to the log file.")
sys.stdout = original_stdout
print("This goes back to the terminal.")Nützliche sys-Attribute
| Attribut / Funktion | Beschreibung |
|---|---|
sys.argv | Liste der Kommandozeilenargumente |
sys.version | Python-Versionsstring |
sys.version_info | Benanntes Tupel aus (major, minor, micro, ...) |
sys.platform | Plattformkennung ("linux", "darwin", "win32") |
sys.path | Modulsuchpfad (Liste von Strings) |
sys.modules | Wörterbuch aller aktuell importierten Module |
sys.stdin | Standard-Eingabestrom |
sys.stdout | Standard-Ausgabestrom |
sys.stderr | Standard-Fehlerstrom |
sys.exit(code) | Interpreter mit dem angegebenen Statuscode beenden |
sys.getrecursionlimit() | Maximale Rekursionstiefe (Standard 1000) |
sys.maxsize | Maximalwert eines int auf dieser Plattform |
os und sys in der Praxis kombinieren
Echte Skripte verwenden oft beide Module zusammen. Hier ist ein kleines, aber realistisches Beispiel: ein Skript, das ein Verzeichnis nach .log-Dateien durchsucht und eine Zusammenfassung ausgibt.
import os
import sys
def summarize_logs(directory):
if not os.path.isdir(directory):
sys.stderr.write(f"Error: '{directory}' is not a directory.\n")
sys.exit(1)
log_files = [
f for f in os.listdir(directory)
if f.endswith(".log") and os.path.isfile(os.path.join(directory, f))
]
if not log_files:
print("No .log files found.")
return
print(f"Found {len(log_files)} log file(s) in '{directory}':")
for name in sorted(log_files):
full_path = os.path.join(directory, name)
size = os.path.getsize(full_path)
print(f" {name} ({size} bytes)")
if len(sys.argv) != 2:
print(f"Usage: python {sys.argv[0]} <directory>")
sys.exit(1)
summarize_logs(sys.argv[1])Führen Sie es als python summarize.py /var/log aus, und es gibt den Namen und die Dateigröße in Bytes jeder .log-Datei in diesem Verzeichnis aus.
os vs. pathlib — Was sollten Sie verwenden?
Python 3.4 führte pathlib.Path ein, eine objektorientierte Alternative zu os.path. Beide Ansätze sind korrekt; die Wahl ist hauptsächlich eine Stilfrage.
| Aufgabe | os-Stil | pathlib-Stil |
|---|---|---|
| Pfade zusammenführen | os.path.join(a, b) | Path(a) / b |
| Dateiname ermitteln | os.path.basename(p) | Path(p).name |
| Erweiterung ermitteln | os.path.splitext(p)[1] | Path(p).suffix |
| Existenz prüfen | os.path.exists(p) | Path(p).exists() |
| Textdatei lesen | open(p).read() | Path(p).read_text() |
| Verzeichnis auflisten | os.listdir(p) | list(Path(p).iterdir()) |
pathlib produziert tendenziell besser lesbaren Code für pfadintensive Skripte; os.path ist vertraut und wird überall dort unterstützt, wo Python 3 läuft. Das Modul sys hat kein pathlib-Äquivalent — es ist immer import sys.
Übungen
Verwandte Kapitel
- Python-Module — eigene Module erstellen und importieren
- Python-Dateiverarbeitung — Dateien lesen und schreiben
- Python Try Except — Fehler aus Datei- und OS-Operationen behandeln
- Python-Variablen — Variablenbereich und Benennung
- Python Scope — wie Python Namen über verschiedene Bereiche hinweg auflöst