29. Interaktion mit dem Betriebssystem: sys und os
Python-Programme existieren nicht isoliert – sie laufen auf einem Betriebssystem, das Dateien, Verzeichnisse, Umgebungseinstellungen und den Start sowie die Kommunikation von Programmen verwaltet. Die Module sys und os stellen Werkzeuge bereit, um mit dieser Umgebung zu interagieren. Damit können Ihre Programme Kommandozeilenargumente akzeptieren, Umgebungsvariablen lesen, im Dateisystem navigieren sowie Verzeichnisse erstellen oder entfernen.
Wenn Sie diese Module verstehen, verwandeln sich Ihre Python-Skripte von isoliertem Code in Programme, die sich in das größere System integrieren, beim Start auf Benutzereingaben reagieren und Dateien und Ordner programmatisch verwalten können.
29.1) Kommandozeilenargumente und die Verwendung von sys.argv
Wenn Sie ein Python-Skript im Terminal oder in der Eingabeaufforderung ausführen, können Sie zusätzliche Informationen übergeben – diese nennt man Kommandozeilenargumente (command-line arguments). Zum Beispiel:
python greet.py Alice 25Hier ist greet.py der Skriptname, und Alice und 25 sind Argumente, die an das Programm übergeben werden. Das Modul sys stellt über sys.argv, eine Liste, die den Skriptnamen und alle Argumente als Strings enthält, Zugriff auf diese Argumente bereit.
29.1.1) Was ist sys.argv?
sys.argv ist eine Liste, in der:
sys.argv[0]immer der Name des ausgeführten Skripts istsys.argv[1],sys.argv[2]usw. die Argumente sind, die nach dem Skriptnamen übergeben werden- alle Elemente Strings sind, selbst wenn sie wie Zahlen aussehen
Erstellen wir ein einfaches Skript, um zu sehen, wie das funktioniert:
# show_args.py
import sys
print("Script name:", sys.argv[0])
print("Number of arguments:", len(sys.argv))
print("All arguments:", sys.argv)Wenn Sie dieses Skript ausführen mit:
python show_args.py hello world 123Output:
Script name: show_args.py
Number of arguments: 4
All arguments: ['show_args.py', 'hello', 'world', '123']Beachten Sie, dass sys.argv 4 Elemente enthält: den Skriptnamen plus drei Argumente. Die Zahl 123 wird als String '123' gespeichert, nicht als Integer.
29.1.2) Kommandozeilenargumente in Programmen verwenden
Kommandozeilenargumente ermöglichen es Benutzern, das Verhalten eines Programms anzupassen, ohne Code zu ändern. Hier ist ein Begrüßungsprogramm, das das erste Argument als Namen verwendet:
# greet.py
import sys
if len(sys.argv) < 2:
print("Usage: python greet.py <name>")
sys.exit(1) # Mit Fehlercode beenden
name = sys.argv[1]
print(f"Hello, {name}!")Ausführen:
python greet.py AliceOutput:
Hello, Alice!Wenn Sie vergessen, einen Namen anzugeben:
python greet.pyOutput:
Usage: python greet.py <name>Das Programm prüft, ob genügend Argumente bereitgestellt wurden. Falls nicht, gibt es eine Usage-Nachricht aus und beendet sich mit sys.exit(1). Die Zahl 1 ist ein Exit-Code (exit code) – gemäß Konvention bedeutet 0 Erfolg und von null verschiedene Werte zeigen Fehler an. Das hilft anderen Programmen oder Skripten festzustellen, ob Ihr Programm erfolgreich ausgeführt wurde.
29.1.3) Argumente in andere Typen umwandeln
Da alle Argumente als Strings ankommen, müssen Sie sie oft konvertieren. Hier ist ein Programm, das die Fläche eines Rechtecks berechnet:
# area.py
import sys
if len(sys.argv) < 3:
print("Usage: python area.py <width> <height>")
sys.exit(1)
try:
width = float(sys.argv[1])
height = float(sys.argv[2])
except ValueError:
print("Error: Width and height must be numbers")
sys.exit(1)
area = width * height
print(f"Area: {area}")Ausführen:
python area.py 5.5 3.2Output:
Area: 17.6Wenn der Benutzer ungültige Eingaben macht:
python area.py five threeOutput:
Error: Width and height must be numbersDer try-except-Block (aus Kapitel 25) behandelt Konvertierungsfehler sauber und gibt hilfreiches Feedback, statt mit einem Traceback abzustürzen.
29.2) Interpreter- und Laufzeitinformationen mit sys abrufen
Das Modul sys liefert Informationen über den Python-Interpreter selbst und die Laufzeitumgebung. Das ist nützlich für Debugging, Logging oder zum Schreiben von Code, der sich an unterschiedliche Python-Versionen oder Plattformen anpasst.
29.2.1) Informationen zur Python-Version
sys.version und sys.version_info sagen Ihnen, welche Python-Version Ihren Code ausführt:
import sys
print("Python version string:", sys.version)
print("Version info:", sys.version_info)
print(f"Major version: {sys.version_info.major}")
print(f"Minor version: {sys.version_info.minor}")Output (example):
Python version string: 3.11.4 (main, Jul 5 2023, 13:45:01) [GCC 11.2.0]
Version info: sys.version_info(major=3, minor=11, micro=4, releaselevel='final', serial=0)
Major version: 3
Minor version: 11sys.version ist ein für Menschen lesbarer String, während sys.version_info ein Named Tuple ist, das Sie programmatisch vergleichen können:
import sys
if sys.version_info < (3, 8):
print("This program requires Python 3.8 or higher")
sys.exit(1)
print("Python version is compatible")Damit stellen Sie sicher, dass Ihr Programm nur auf unterstützten Python-Versionen läuft.
29.2.2) Plattforminformationen
sys.platform identifiziert das Betriebssystem:
import sys
print("Platform:", sys.platform)
if sys.platform == "win32":
print("Running on Windows")
elif sys.platform == "darwin":
print("Running on macOS")
elif sys.platform.startswith("linux"):
print("Running on Linux")
else:
print("Running on another platform")Output (on Linux):
Platform: linux
Running on LinuxSo können Sie bei Bedarf plattformspezifischen Code schreiben, z. B. unterschiedliche Dateipfade oder Systemkommandos verwenden.
29.2.3) Modulsuchpfad
sys.path ist eine Liste von Verzeichnissen, die Python beim Importieren von Modulen durchsucht:
import sys
print("Module search paths:")
for path in sys.path:
print(f" {path}")Output (example):
Module search paths:
/home/user/projects
/usr/lib/python3.11
/usr/lib/python3.11/lib-dynload
/home/user/.local/lib/python3.11/site-packagesDer erste Eintrag ist normalerweise das Verzeichnis, das Ihr Skript enthält. Python durchsucht diese Pfade der Reihe nach, wenn Sie import verwenden. Das Verständnis von sys.path hilft beim Debuggen von Import-Fehlern oder beim Hinzufügen eigener Modulverzeichnisse.
29.2.4) Programme mit Exit-Codes beenden
Wir haben gesehen, dass sys.exit() verwendet wird, um Programme zu stoppen. Sie können einen Exit-Code übergeben, um Erfolg oder Fehlschlag anzuzeigen:
import sys
def process_data(filename):
try:
with open(filename) as f:
data = f.read()
# Daten verarbeiten...
return True
except FileNotFoundError:
print(f"Error: File '{filename}' not found", file=sys.stderr)
return False
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python script.py <filename>", file=sys.stderr)
sys.exit(1)
success = process_data(sys.argv[1])
sys.exit(0 if success else 1)Exit-Codes folgen Unix-Konventionen:
0bedeutet Erfolg- von null verschiedene Werte zeigen unterschiedliche Fehlerarten an
- andere Programme können diese Codes prüfen, um festzustellen, ob Ihr Programm erfolgreich war
29.3) Zugriff auf Umgebungsvariablen mit os
Umgebungsvariablen (environment variables) sind Schlüssel-Wert-Paare, die vom Betriebssystem oder vom Benutzer gesetzt werden und die Programme lesen können. Sie werden für Konfigurationen, zum Speichern von Pfaden, API-Keys und anderen Einstellungen verwendet, die nicht fest im Code stehen sollten.
29.3.1) Umgebungsvariablen lesen
Das Modul os stellt os.environ bereit, ein dictionary-ähnliches Objekt, das alle Umgebungsvariablen enthält:
import os
# Eine bestimmte Umgebungsvariable holen
home = os.environ.get('HOME') # Auf Unix/Linux/macOS
print(f"Home directory: {home}")
# Gibt None zurück, wenn die Variable nicht existiert
api_key = os.environ.get('MY_API_KEY')
print(f"API key: {api_key}")Output (on Linux):
Home directory: /home/alice
API key: NoneSie können einen Standardwert angeben:
import os
# Umgebungsvariable mit Standardwert holen
log_level = os.environ.get('LOG_LEVEL', 'INFO')
print(f"Log level: {log_level}")Output (if LOG_LEVEL not set):
Log level: INFO29.3.2) Häufige Umgebungsvariablen
Verschiedene Betriebssysteme stellen Standard-Umgebungsvariablen bereit:
import os
# Plattformübergreifende Variablen
print("Path:", os.environ.get('PATH'))
# Unix/Linux/macOS
print("User:", os.environ.get('USER'))
print("Home:", os.environ.get('HOME'))
print("Shell:", os.environ.get('SHELL'))
# Windows
print("User", os.environ.get('USERNAME'))
print("User Profile:", os.environ.get('USERPROFILE'))
print("Temp:", os.environ.get('TEMP'))PATH ist besonders wichtig – sie listet Verzeichnisse auf, in denen das System nach ausführbaren Programmen sucht. Wenn Sie einen Befehl wie python eingeben, durchsucht das System diese Verzeichnisse.
29.3.3) Umgebungsvariablen setzen
Sie können Umgebungsvariablen für Ihr Programm und alle Subprozesse, die es erstellt, ändern:
import os
# Eine Umgebungsvariable setzen
os.environ['MY_CONFIG'] = 'production'
# Wieder auslesen
print(os.environ.get('MY_CONFIG')) # Output: production
# Eine Umgebungsvariable löschen
del os.environ['MY_CONFIG']Wichtig: Änderungen an os.environ betreffen nur den aktuellen Python-Prozess und alle Programme, die er startet. Sie bleiben nicht erhalten, nachdem Ihr Programm beendet wurde, und beeinflussen keine anderen Programme.
29.4) Arbeiten mit Dateipfaden und Verzeichnissen (os.path, os.getcwd)
Dateipfade korrekt zu verwalten ist entscheidend für Programme, die mit Dateien arbeiten. Die Module os und os.path bieten Werkzeuge, um Pfade plattformunabhängig zu bauen, zu manipulieren und abzufragen.
29.4.1) Das aktuelle Arbeitsverzeichnis ermitteln
Das aktuelle Arbeitsverzeichnis (current working directory, CWD) ist der Ordner, den Ihr Programm als Ausgangspunkt für relative Pfade betrachtet:
import os
cwd = os.getcwd()
print(f"Current working directory: {cwd}")Output (example):
Current working directory: /home/alice/projects/myappWenn Sie eine Datei mit einem relativen Pfad wie 'data.txt' öffnen, sucht Python im aktuellen Arbeitsverzeichnis. Das Verständnis des CWD hilft beim Debuggen von „file not found“-Fehlern.
29.4.2) Das aktuelle Verzeichnis ändern
Sie können das Arbeitsverzeichnis mit os.chdir() ändern:
import os
original = os.getcwd()
print("Original directory:", original)
# In ein anderes Verzeichnis wechseln
os.chdir('/tmp')
print("New directory:", os.getcwd())
# Zurückwechseln
os.chdir(original)
print("Back to:", os.getcwd())Output:
Original directory: /home/alice/projects
New directory: /tmp
Back to: /home/alice/projectsHinweis: In Kapitel 28 haben Sie contextlib.chdir() kennengelernt, das das ursprüngliche Verzeichnis automatisch wiederherstellt. Für einfache Verzeichniswechsel sollten Sie bevorzugt den Context Manager verwenden:
from contextlib import chdir
with chdir('/tmp'):
print("Temporarily in:", os.getcwd())
# Automatically restoredSo stellen Sie sicher, dass das Verzeichnis immer wiederhergestellt wird, selbst wenn ein Fehler auftritt.
29.4.3) Pfade mit os.path.join() zusammensetzen
Unterschiedliche Betriebssysteme verwenden unterschiedliche Pfadtrenner:
- Unix/Linux/macOS:
/(forward slash) - Windows:
\(backslash)
os.path.join() setzt Pfade korrekt für die aktuelle Plattform zusammen:
import os
# Einen Pfad zu einer Datei in einem Unterverzeichnis erstellen
data_dir = 'data'
filename = 'users.txt'
filepath = os.path.join(data_dir, filename)
print(f"File path: {filepath}")Output (on Unix/Linux/macOS):
File path: data/users.txtOutput (on Windows):
File path: data\users.txtSie können mehrere Komponenten zusammenfügen:
import os
base = '/home/alice'
project = 'myapp'
subdir = 'data'
file = 'config.json'
full_path = os.path.join(base, project, subdir, file)
print(full_path) # Output: /home/alice/myapp/data/config.jsonDie Verwendung von os.path.join() macht Ihren Code portabel über Betriebssysteme hinweg.
29.4.4) Prüfen, ob Pfade existieren
Bevor Sie mit Dateien oder Verzeichnissen arbeiten, prüfen Sie, ob sie existieren:
import os
path = 'data.txt'
if os.path.exists(path):
print(f"'{path}' exists")
else:
print(f"'{path}' does not exist")Sie können auch gezielt auf Dateien oder Verzeichnisse prüfen:
import os
path = 'mydir'
if os.path.isfile(path):
print(f"'{path}' is a file")
elif os.path.isdir(path):
print(f"'{path}' is a directory")
elif os.path.exists(path):
print(f"'{path}' exists but is neither a file nor directory")
else:
print(f"'{path}' does not exist")Diese Prüfungen verhindern Fehler, wenn Sie versuchen, nicht vorhandene Dateien zu öffnen oder nicht vorhandene Verzeichnisse aufzulisten.
29.4.5) Absolute Pfade ermitteln
os.path.abspath() konvertiert relative Pfade in absolute Pfade:
import os
relative_path = 'data/users.txt'
absolute_path = os.path.abspath(relative_path)
print(f"Relative: {relative_path}")
print(f"Absolute: {absolute_path}")Output (example):
Relative: data/users.txt
Absolute: /home/alice/projects/myapp/data/users.txtDas ist nützlich für Logging, Fehlermeldungen oder wenn Sie den exakten Speicherort einer Datei kennen müssen.
29.4.6) Pfade in Bestandteile aufteilen
os.path.split() trennt einen Pfad in Verzeichnis und Dateiname:
import os
path = '/home/alice/projects/data.txt'
directory, filename = os.path.split(path)
print(f"Directory: {directory}")
print(f"Filename: {filename}")Output:
Directory: /home/alice/projects
Filename: data.txtos.path.basename() liefert nur den Dateinamen, und os.path.dirname() liefert nur das Verzeichnis:
import os
path = '/home/alice/projects/data.txt'
print(f"Basename: {os.path.basename(path)}") # Output: data.txt
print(f"Dirname: {os.path.dirname(path)}") # Output: /home/alice/projects29.4.7) Dateiendungen aufteilen
os.path.splitext() trennt den Dateinamen von seiner Endung:
import os
filename = 'report.pdf'
name, extension = os.path.splitext(filename)
print(f"Name: {name}") # Output: report
print(f"Extension: {extension}") # Output: .pdfDas ist nützlich, um Dateien basierend auf ihrem Typ zu verarbeiten:
import os
files = ['data.csv', 'image.png', 'document.txt', 'script.py']
for file in files:
name, ext = os.path.splitext(file)
if ext == '.csv':
print(f"Process CSV file: {file}")
elif ext == '.png':
print(f"Process image file: {file}")Output:
Process CSV file: data.csv
Process image file: image.png29.5) Dateien und Verzeichnisse auflisten, erstellen und entfernen
Das Modul os bietet Funktionen, um das Dateisystem zu manipulieren: Verzeichnisinhalte auflisten, neue Verzeichnisse erstellen sowie Dateien und Ordner entfernen.
29.5.1) Verzeichnisinhalte auflisten
os.listdir() gibt eine Liste aller Elemente in einem Verzeichnis zurück:
import os
# Inhalt des aktuellen Verzeichnisses auflisten
contents = os.listdir('.')
print("Current directory contents:")
for item in contents:
print(f" {item}")Output (example):
Current directory contents:
script.py
data.txt
mydir
README.mdDie Liste enthält sowohl Dateien als auch Verzeichnisse. Um zwischen ihnen zu unterscheiden:
import os
contents = os.listdir('.')
print("Files:")
for item in contents:
if os.path.isfile(item):
print(f" {item}")
print("\nDirectories:")
for item in contents:
if os.path.isdir(item):
print(f" {item}")Output:
Files:
script.py
data.txt
README.md
Directories:
mydir29.5.2) Verzeichnisse erstellen
os.mkdir() erstellt ein einzelnes Verzeichnis:
import os
new_dir = 'output'
if not os.path.exists(new_dir):
os.mkdir(new_dir)
print(f"Created directory: {new_dir}")
else:
print(f"Directory already exists: {new_dir}")Output:
Created directory: outputWichtig: os.mkdir() schlägt fehl, wenn das übergeordnete Verzeichnis nicht existiert. Zum Beispiel wird beim Versuch, 'data/output' zu erstellen, wenn 'data' nicht existiert, ein Fehler ausgelöst.
os.makedirs() erstellt alle notwendigen übergeordneten Verzeichnisse:
import os
nested_dir = 'data/processed/2024'
if not os.path.exists(nested_dir):
os.makedirs(nested_dir)
print(f"Created directory structure: {nested_dir}")Output:
Created directory structure: data/processed/2024Dies erstellt data, dann data/processed, dann data/processed/2024, falls sie nicht existieren.
29.5.3) Dateien entfernen
os.remove() löscht eine Datei:
import os
filename = 'temp.txt'
# Eine temporäre Datei erstellen
with open(filename, 'w') as f:
f.write('Temporary data')
print(f"File exists: {os.path.exists(filename)}") # Output: True
# Die Datei entfernen
os.remove(filename)
print(f"File exists: {os.path.exists(filename)}") # Output: FalseWarnung: os.remove() löscht Dateien dauerhaft – sie landen nicht im Papierkorb.
29.5.4) Verzeichnisse entfernen
os.rmdir() entfernt ein leeres Verzeichnis:
import os
directory = 'empty_dir'
# Ein leeres Verzeichnis erstellen und dann entfernen
os.mkdir(directory)
print(f"Created: {directory}")
os.rmdir(directory)
print(f"Removed: {directory}")os.rmdir() schlägt fehl, wenn das Verzeichnis Dateien enthält. Um ein Verzeichnis und seinen gesamten Inhalt zu entfernen, müssen Sie zuerst die Dateien löschen:
import os
def remove_directory_contents(directory):
"""Alle Dateien in einem Verzeichnis entfernen und dann das Verzeichnis entfernen.
Hinweis: Schlägt fehl, wenn das Verzeichnis Unterverzeichnisse enthält.
"""
if not os.path.exists(directory):
print(f"Directory does not exist: {directory}")
return
# Alle Dateien im Verzeichnis entfernen
for item in os.listdir(directory):
item_path = os.path.join(directory, item)
if os.path.isfile(item_path):
os.remove(item_path)
print(f"Removed file: {item_path}")
# Das nun leere Verzeichnis entfernen
os.rmdir(directory)
print(f"Removed directory: {directory}")
# Beispielverwendung
test_dir = 'test_data'
os.makedirs(test_dir, exist_ok=True)
# Einige Testdateien erstellen
with open(os.path.join(test_dir, 'file1.txt'), 'w') as f:
f.write('test')
with open(os.path.join(test_dir, 'file2.txt'), 'w') as f:
f.write('test')
# Alles entfernen
remove_directory_contents(test_dir)Output:
Removed file: test_data/file1.txt
Removed file: test_data/file2.txt
Removed directory: test_dataHinweis: Für komplexeres Entfernen von Verzeichnissen (einschließlich Unterverzeichnissen) stellt Pythons Modul shutil shutil.rmtree() bereit, aber das geht über unseren aktuellen Umfang hinaus.
29.5.5) Dateien und Verzeichnisse umbenennen
os.rename() benennt Dateien und Verzeichnisse um oder verschiebt sie:
import os
# Eine Datei umbenennen
old_name = 'draft.txt'
new_name = 'final.txt'
# Testdatei erstellen
with open(old_name, 'w') as f:
f.write('content')
os.rename(old_name, new_name)
print(f"Renamed '{old_name}' to '{new_name}'")Sie können Dateien auch in andere Verzeichnisse verschieben:
import os
# Verzeichnisse und Datei erstellen
os.makedirs('source', exist_ok=True)
os.makedirs('destination', exist_ok=True)
with open('source/file.txt', 'w') as f:
f.write('content')
# Datei in ein anderes Verzeichnis verschieben
os.rename('source/file.txt', 'destination/file.txt')
print("Moved file to destination directory")Die Module sys und os geben Ihren Python-Programmen die Fähigkeit, mit dem Betriebssystem zu interagieren, Kommandozeileneingaben zu akzeptieren, Konfigurationen zu lesen sowie Dateien und Verzeichnisse zu verwalten. Diese Fähigkeiten verwandeln einfache Skripte in leistungsfähige Kommandozeilenwerkzeuge, die sich nahtlos in die breitere Systemumgebung integrieren.