Datentypen und Kontrollstrukturen¶
Die wichtigsten Datentypen, Datenstrukturen und Kontrollstrukturen von Python für typische Automatisierungs- und Administrationsaufgaben einsetzen.
Bevor Dateien verarbeitet, APIs abgefragt oder Systeme automatisiert werden können, müssen Daten in Python gespeichert, verändert und ausgewertet werden.
Python stellt dafür eine Reihe eingebauter Datentypen und Datenstrukturen bereit. Zahlen, Texte, Listen und Dictionaries gehören zu den wichtigsten Werkzeugen im Alltag eines Administrators.
Ebenso wichtig sind Kontrollstrukturen. Bedingungen und Schleifen ermöglichen es, auf unterschiedliche Situationen zu reagieren, Dateien zu durchsuchen oder große Mengen von Daten automatisiert zu verarbeiten.
In diesem Kapitel lernen Sie die wichtigsten Datentypen und Kontrollstrukturen kennen und erfahren, wie diese in typischen Automatisierungsaufgaben eingesetzt werden.
Dieses Wissen bildet die Grundlage für nahezu jedes Python-Skript.
Grundlegende Datentypen¶
Zahlen: Ganzzahlen und Fließkommazahlen¶
In der Systemadministration begegnen Ihnen häufig Zahlen, etwa bei der Auswertung von Speichergrößen, CPU-Auslastungen oder Zeitangaben. Python unterscheidet vor allem zwischen int (Ganzzahlen) und float (Fließkommazahlen).
# Speichergröße in Megabyte
speicher_mb = 2048 # int
# CPU-Auslastung in Prozent
cpu_last = 75.5 # float
# Beispiel: Umrechnung von MB in GB
speicher_gb = speicher_mb / 1024
print(f"Speicher: {speicher_gb} GB") # Ausgabe: Speicher: 2.0 GB
Strings: Textdaten sicher verarbeiten¶
Strings sind unverzichtbar, wenn Sie Dateipfade, Logeinträge, Befehle oder API-Antworten verarbeiten.
# Beispiel: Logdatei-Zeile analysieren
log_zeile = "2024-06-01 12:00:00 ERROR Server nicht erreichbar"
# Prüfen, ob Fehler in der Zeile steht
if "ERROR" in log_zeile:
print("Fehler gefunden")
Strings können mit einfachen ('...') oder doppelten ("...") Anführungszeichen definiert werden. Für mehrzeilige Texte gibt es dreifache Anführungszeichen.
Boolesche Werte: Wahrheitswerte für Entscheidungen¶
Boolesche Werte True und False sind essenziell, um Bedingungen zu steuern – etwa, ob ein Dienst läuft oder eine Datei existiert.
# Prüfen, ob eine Datei existiert
import os
datei_vorhanden = os.path.exists("/var/log/syslog")
if datei_vorhanden:
print("Logdatei gefunden")
else:
print("Logdatei fehlt")
In Python sind boolesche Werte eigene Typen, keine Ganzzahlen wie in C. Das macht Bedingungen klarer und vermeidet Fehler.
None: Das Fehlen eines Werts ausdrücken¶
None steht für "kein Wert" oder "nicht gesetzt" – vergleichbar mit null in anderen Sprachen. Es ist nützlich, um z.B. das Ergebnis einer Suche oder eines API-Calls zu kennzeichnen, wenn keine Daten vorliegen.
# Beispiel: Funktion, die einen Wert oder None zurückgibt
def finde_server_ip(name: str):
server_ips = {"web01": "192.168.1.10", "db01": "192.168.1.20"}
return server_ips.get(name) # Gibt IP oder None zurück
ip = finde_server_ip("web02")
if ip is None:
print("Server nicht gefunden")
else:
print(f"Server-IP: {ip}")
Zusammenfassung¶
- Zahlen (
int,float) sind die Basis für Messwerte und Berechnungen. - Strings verarbeiten Textdaten, z.B. Logeinträge oder Pfade.
- Boolesche Werte steuern Programmfluss durch Wahrheitswerte.
- None signalisiert das Fehlen eines Werts, wichtig für Fehlerbehandlung und optionale Daten.
Diese Datentypen bilden das Fundament, um Automatisierungsskripte robust und verständlich zu gestalten. Im Vergleich zu Shell-Skripten bietet Python hier mehr Ausdruckskraft und weniger Fehlerquellen, was gerade bei komplexen Administrationsaufgaben entscheidend ist.
Listen, Sets und Dictionaries¶
Listen: Geordnete Sammlungen mit Duplikaten¶
Listen sind die flexibelste und am häufigsten genutzte Datenstruktur in Python, wenn es darum geht, mehrere Werte in einer festen Reihenfolge zu speichern. Anders als Arrays in C oder Java müssen Listen nicht vorab in ihrer Größe definiert werden und können Elemente verschiedener Typen enthalten.
In der Systemadministration sind Listen ideal, um beispielsweise Zeilen einer Logdatei, IP-Adressen von Servern oder Befehlsausgaben zu speichern und zu verarbeiten.
# Beispiel: Liste der aktiven Dienste
aktive_dienste = ["ssh", "nginx", "docker", "cron"]
# Dienste hinzufügen
aktive_dienste.append("fail2ban")
# Zugriff auf einzelne Elemente
print(aktive_dienste[0]) # Ausgabe: ssh
# Iteration über die Liste
for dienst in aktive_dienste:
print(f"Dienst läuft: {dienst}")
Listen sind veränderbar (mutable), das heißt, Sie können Elemente hinzufügen, entfernen oder ändern. Das ist besonders praktisch, wenn Sie dynamisch Daten sammeln, z.B. beim Einlesen von Logdateien oder beim Abfragen von Serverlisten.
Sets: Ungeordnete Mengen ohne Duplikate¶
Sets sind ideal, wenn Sie eine Sammlung von eindeutigen Elementen benötigen und die Reihenfolge keine Rolle spielt. Das ist häufig der Fall bei IP-Adressen, Benutzernamen oder anderen Identifikatoren, bei denen Duplikate unerwünscht sind.
# Beispiel: Einzigartige IP-Adressen aus Logdatei
ip_adressen = set()
ip_adressen.add("192.168.1.10")
ip_adressen.add("10.0.0.5")
ip_adressen.add("192.168.1.10") # Duplikat wird ignoriert
print(ip_adressen) # Ausgabe: {'192.168.1.10', '10.0.0.5'}
Sets unterstützen effiziente Mengenoperationen wie Schnittmengen, Vereinigungen oder Differenzen, was z.B. beim Vergleich von Benutzergruppen oder Serverpools sehr hilfreich ist.
backup_server = {"srv01", "srv02", "srv03"}
live_server = {"srv02", "srv03", "srv04"}
# Server, die nur im Backup sind
nur_backup = backup_server - live_server
print(nur_backup) # {'srv01'}
Dictionaries: Schlüssel-Wert-Paare für strukturierte Daten¶
Dictionaries (Wörterbücher) speichern Daten als Schlüssel-Wert-Paare. Sie sind perfekt geeignet, um z.B. Konfigurationsparameter, Benutzerinformationen oder API-Antworten abzubilden.
# Beispiel: Serverstatus mit IP als Schlüssel
server_status = {
"192.168.1.10": "online",
"192.168.1.11": "offline",
"192.168.1.12": "wartung"
}
# Status eines Servers abfragen
ip = "192.168.1.10"
status = server_status.get(ip, "unbekannt")
print(f"Server {ip} ist {status}")
Dictionaries sind sehr performant beim Zugriff auf Werte über Schlüssel, was bei großen Datenmengen oder häufigen Abfragen entscheidend ist.
Praxis-Tipp: Auswahl der richtigen Datenstruktur¶
- Verwenden Sie Listen, wenn die Reihenfolge wichtig ist oder Duplikate erlaubt sind.
- Nutzen Sie Sets, wenn Sie eindeutige Elemente ohne Reihenfolge benötigen.
- Greifen Sie zu Dictionaries, wenn Sie Daten mit einem eindeutigen Schlüssel verknüpfen wollen.
Zusammenfassung¶
Mit Listen, Sets und Dictionaries können Sie in Python Daten aus Logs, Konfigurationen oder APIs strukturiert und effizient verwalten. Diese Datenstrukturen bilden die Grundlage für viele Automatisierungsaufgaben und erleichtern das Schreiben klarer, wartbarer Skripte im Administrationsalltag.
Operatoren und Ausdrücke¶
Arithmetische Operatoren¶
Python unterstützt die grundlegenden arithmetischen Operatoren, die Sie aus anderen Sprachen kennen:
+Addition-Subtraktion*Multiplikation/Division (ergibt immer einen float)//Ganzzahlige Division (abrunden)%Modulo (Rest einer Division)**Potenzierung
Diese Operatoren sind essenziell, wenn Sie beispielsweise Ressourcenverbrauch berechnen, Zeitspannen auswerten oder Speichergrößen umrechnen.
# Beispiel: Berechnung der durchschnittlichen CPU-Auslastung
cpu_times = [12.5, 15.0, 10.0, 20.5] # in Prozent
average_cpu = sum(cpu_times) / len(cpu_times)
print(f"Durchschnittliche CPU-Auslastung: {average_cpu:.2f}%")
# Beispiel: Umrechnung von Bytes in Megabyte
bytes_size = 10485760 # 10 MB
megabytes = bytes_size / (1024 ** 2)
print(f"Dateigröße: {megabytes} MB")
Vergleichsoperatoren¶
Vergleichsoperatoren liefern True oder False zurück und sind unverzichtbar für Entscheidungen und Filterungen:
==Gleichheit!=Ungleichheit<,<=,>,>=Größenvergleiche
In der Administration helfen sie z.B., um Logeinträge nach Datum zu filtern oder Statuscodes zu prüfen.
# Beispiel: Prüfen, ob eine Logdatei älter als 7 Tage ist
from datetime import datetime, timedelta
log_date = datetime(2024, 4, 20)
if datetime.now() - log_date > timedelta(days=7):
print("Logdatei ist älter als 7 Tage, Backup empfohlen.")
Logische Operatoren¶
Logische Operatoren verbinden mehrere Bedingungen:
and(und)or(oder)not(nicht)
Diese sind besonders nützlich, wenn Sie komplexe Prüfungen durchführen, z.B. bei Monitoring-Skripten.
# Beispiel: Überwachung eines Servers
cpu_load = 85 # in Prozent
memory_free = 500 # in MB
if cpu_load > 80 and memory_free < 1000:
print("Warnung: Hohe CPU-Auslastung und wenig freier Speicher.")
if not cpu_load > 90 or memory_free > 200:
print("System ist im Normalbereich.")
Mitgliedschaftsoperatoren¶
Mit in und not in prüfen Sie, ob ein Wert in einer Sammlung enthalten ist. Das ist oft praktischer als umständliche Schleifen.
# Beispiel: Überprüfen, ob ein Service in der Liste der überwachten Dienste ist
services = ["nginx", "mysql", "redis"]
service_to_check = "mysql"
if service_to_check in services:
print(f"Service {service_to_check} wird überwacht.")
else:
print(f"Service {service_to_check} ist nicht in der Überwachungsliste.")
Best Practices¶
- Verwenden Sie
//für ganzzahlige Division, wenn Sie keine Nachkommastellen benötigen (z.B. bei Zeiteinheiten). - Nutzen Sie Klammern, um komplexe logische Ausdrücke übersichtlich zu gestalten.
- Prüfen Sie Mitgliedschaften mit
instatt mit Schleifen für bessere Lesbarkeit und Performance.
Zusammenfassung¶
Operatoren und Ausdrücke sind das Fundament, um in Python Entscheidungen zu treffen und Werte zu berechnen. Für Administratoren bedeutet das: Sie können mit wenigen Zeilen Skript Logik abbilden, die in Shell-Skripten oft komplexer und fehleranfälliger ist. Nutzen Sie die klaren, lesbaren Operatoren, um Ihre Automatisierung robust und verständlich zu gestalten.
Bedingungen mit if, elif und else¶
Grundlagen von bedingten Anweisungen¶
Bedingte Anweisungen sind essenziell, um Programme flexibel auf unterschiedliche Situationen reagieren zu lassen. In Python steuern wir den Programmfluss mit if, elif und else.
Die Syntax ist klar und lesbar:
if bedingung:
# Codeblock, wenn Bedingung wahr ist
elif andere_bedingung:
# Codeblock, wenn andere Bedingung wahr ist
else:
# Codeblock, wenn keine Bedingung wahr ist
Warum Bedingungen in der Administration wichtig sind¶
In der Systemadministration sind Entscheidungen oft datenabhängig: etwa, ob ein Backup gestartet wird, wenn genügend Speicherplatz vorhanden ist, oder ob ein Service neu gestartet werden muss, wenn er nicht reagiert. Bedingungen erlauben es, solche Entscheidungen programmatisch abzubilden.
Beispiel: Überprüfen von Festplattenplatz¶
Ein häufiges Szenario ist das Überwachen des freien Speicherplatzes und das Auslösen eines Alarms, wenn der Platz unter einen Schwellenwert fällt.
import shutil
# Pfad der zu überprüfenden Partition
partition = "/"
# Freier Speicherplatz in Bytes
frei = shutil.disk_usage(partition).free
# Schwellenwert: 1 GB
schwelle = 1 * 1024**3
if frei < schwelle:
print(f"Warnung: Wenig Speicherplatz auf {partition} ({frei / 1024**3:.2f} GB frei)")
else:
print(f"Speicherplatz auf {partition} ist ausreichend ({frei / 1024**3:.2f} GB frei)")
Mehrere Bedingungen mit elif¶
Manchmal sind mehrstufige Entscheidungen nötig, z.B. unterschiedliche Reaktionen je nach Schweregrad:
if frei < 500 * 1024**2: # weniger als 500 MB
print("Kritischer Speicherplatzmangel! Sofort handeln!")
elif frei < 2 * 1024**3: # weniger als 2 GB
print("Warnung: Speicherplatz wird knapp.")
else:
print("Speicherplatz ist in Ordnung.")
Bedingungen mit logischen Operatoren¶
Oft müssen mehrere Bedingungen kombiniert werden, z.B. Status eines Dienstes und freier Speicherplatz:
service_laeuft = False
frei = 3 * 1024**3 # 3 GB frei
if not service_laeuft and frei > 1 * 1024**3:
print("Starte Dienst, da er nicht läuft und genug Speicher vorhanden ist.")
else:
print("Keine Aktion erforderlich.")
Best Practice: Lesbarkeit und Eindeutigkeit¶
- Verwenden Sie sprechende Variablennamen, z.B.
freier_speicherstattx. - Vermeiden Sie zu komplexe Bedingungen in einer Zeile, teilen Sie sie ggf. auf.
- Nutzen Sie
elif, um mehrere Alternativen klar zu strukturieren.
Zusammenfassung¶
Bedingungen mit if, elif und else sind das Rückgrat für Entscheidungslogik in Python-Skripten. Sie ermöglichen es, Automatisierungsaufgaben situationsabhängig zu steuern – etwa beim Monitoring, der Fehlerbehandlung oder der Ressourcenverwaltung. Das klare und einfache Syntaxdesign von Python erleichtert den Umstieg von Shell-Skripten und erhöht die Wartbarkeit Ihrer Automatisierungslösungen.
Schleifen und Iteration¶
Grundlagen von Schleifen in Python¶
Schleifen sind in der Systemadministration unverzichtbar, um wiederkehrende Aufgaben zu automatisieren, etwa das Auslesen mehrerer Logdateien oder das Überprüfen von Serverzuständen. Python bietet zwei Hauptarten von Schleifen: for-Schleifen und while-Schleifen.
Die for-Schleife: Iteration über Sammlungen¶
Die for-Schleife in Python iteriert direkt über Elemente von Listen, Dateien oder anderen iterierbaren Objekten. Anders als in Sprachen wie Java oder C#, wo man oft mit Zählern und Indizes arbeitet, ist Python hier deutlich eleganter und lesbarer.
Beispiel: Logdateien in einem Verzeichnis auslesen¶
import os
log_dir = '/var/log/myapp'
for filename in os.listdir(log_dir):
if filename.endswith('.log'):
filepath = os.path.join(log_dir, filename)
with open(filepath, 'r', encoding='utf-8') as file:
print(f'Inhalt von {filename}:')
for line in file:
if 'ERROR' in line:
print(line.strip())
Hier iterieren wir über alle Dateien im Verzeichnis, prüfen die Endung und lesen dann Zeile für Zeile, um Fehler zu finden. Diese Art der Iteration ist idiomatisch und vermeidet unnötige Zähler.
Die while-Schleife: Wiederholung bei Bedingungen¶
while-Schleifen führen ihren Block so lange aus, wie eine Bedingung True ist. Sie eignen sich gut für Situationen, in denen die Anzahl der Durchläufe nicht vorher bekannt ist.
Beispiel: Auf Dienstverfügbarkeit warten¶
import time
import socket
host = '192.168.1.100'
port = 22
while True:
with socket.socket() as sock:
result = sock.connect_ex((host, port))
if result == 0:
print(f'Dienst auf {host}:{port} ist erreichbar')
break
else:
print(f'Warte auf Dienst auf {host}:{port}...')
time.sleep(5)
Dieses Skript prüft in einer Endlosschleife, ob ein SSH-Dienst erreichbar ist, und wartet bei Nichterreichbarkeit. Die Schleife endet erst, wenn die Verbindung erfolgreich ist.
Schleifensteuerung: break und continue¶
breakbeendet die Schleife vorzeitig, z.B. wenn ein Fehler gefunden oder ein Ziel erreicht wurde.continueüberspringt den aktuellen Durchlauf und fährt mit dem nächsten fort.
Beispiel: Verzeichnisse durchsuchen und nur relevante Dateien verarbeiten¶
import os
backup_dir = '/backup'
for root, dirs, files in os.walk(backup_dir):
for file in files:
if not file.endswith('.tar.gz'):
continue # Nur Archivdateien verarbeiten
filepath = os.path.join(root, file)
if os.path.getsize(filepath) == 0:
print(f'Warnung: Leere Datei {filepath}')
break # Abbruch bei leerer Datei
print(f'Verarbeite {filepath}')
Best Practices¶
- Verwenden Sie
for-Schleifen, wenn Sie über eine bekannte Sammlung iterieren. - Nutzen Sie
whilefür unbestimmte Wiederholungen, z.B. Polling oder Wartezeiten. - Vermeiden Sie unnötige Zählervariablen, Python unterstützt direkte Iteration.
- Verwenden Sie
breakundcontinuesparsam, um die Lesbarkeit zu erhalten. - Achten Sie bei Dateioperationen auf das sichere Öffnen mit
with.
Zusammenfassung¶
Schleifen sind essenziell für Automatisierungsaufgaben in der Administration. Python macht das Iterieren über Dateien, Netzwerkelemente oder Datenquellen einfach und lesbar. Der Fokus liegt auf klarer, idiomatischer Syntax, die typische Shell- oder Batch-Skripte in vielen Fällen überlegen ist.