Hello World
print("Hallo, Welt!")
print() gibt einen Wert im Terminal beziehungsweise in der Konsole aus.
Python ist eine universell einsetzbare Programmiersprache, die sich durch eine vergleichsweise klare, gut lesbare Syntax auszeichnet. Sie eignet sich hervorragend für Automatisierung, Datenverarbeitung, Webentwicklung, wissenschaftliche Anwendungen, kleine Hilfsprogramme, Kommandozeilenwerkzeuge, Serveranwendungen, Raspberry-Pi-Projekte, Elektronik, Schnittstellenkommunikation und viele weitere Aufgaben.
Eine der großen Stärken von Python besteht darin, dass einfache Programme tatsächlich einfach aussehen können. Gleichzeitig wächst die Sprache problemlos mit: Vom fünfzeiligen Skript zum automatischen Zusammenführen von CSV-Dateien bis hin zu umfangreichen Anwendungen mit Datenbanken, Webservern oder Hardwareansteuerung ist vieles mit derselben Sprache möglich.
Diese Übersicht ist nicht bloß als Cheatsheet gedacht, sondern als kompaktes deutschsprachiges Nachschlagewerk. Die Beispiele konzentrieren sich bewusst auf jene Sprachmittel und Werkzeuge, die man in echten Projekten regelmäßig benötigt.
Python wird üblicherweise als interpretierte Sprache verwendet. Ein Python-Programm wird
in einer Datei mit der Endung .py gespeichert und anschließend vom
Python-Interpreter ausgeführt.
print("Hallo, Welt!")
print() gibt einen Wert im Terminal beziehungsweise in der Konsole aus.
python programm.py
Je nach System wird auch folgender Befehl verwendet:
python3 programm.py
temperatur = 20
if temperatur > 15:
print("Es ist mild.")
print("Programmende")
Python verwendet keine geschweiften Klammern für Codeblöcke. Die Einrückung bestimmt die Struktur des Programms.
Als Konvention werden pro Einrückungsebene vier Leerzeichen verwendet.
if bedingung:
if weitere_bedingung:
print("Zwei Ebenen eingerückt")
Tabs und Leerzeichen wild zu vermischen ist eine zuverlässige Methode, sich selbst unnötige Schwierigkeiten zu bereiten.
# Das ist ein Kommentar.
temperatur = 21 # Kommentar am Zeilenende
Kommentare erklären vor allem das Warum. Offensichtlichen Code noch einmal in Prosa nachzuerzählen bringt wenig.
def berechne_flaeche(breite, hoehe):
"""
Berechnet die Fläche eines Rechtecks.
Parameter:
breite: Breite des Rechtecks
hoehe: Höhe des Rechtecks
"""
return breite * hoehe
Dreifache Anführungszeichen werden häufig für Dokumentationsstrings von Funktionen, Klassen und Modulen verwendet.
Variablen speichern Referenzen auf Werte. Anders als etwa in C oder Java muss der Datentyp einer Variablen normalerweise nicht ausdrücklich angegeben werden.
name = "Julian"
alter = 28
temperatur = 21.5
ist_online = True
x, y, z = 10, 20, 30
print(x)
print(y)
print(z)
a = 10
b = 20
a, b = b, a
print(a) # 20
print(b) # 10
Eine temporäre Hilfsvariable ist dafür in Python nicht notwendig.
MAXIMALE_TEMPERATUR = 80
DATEINAME = "daten.csv"
Python besitzt keine echten Konstanten. Großgeschriebene Namen sind eine Konvention: „Dieser Wert soll nicht verändert werden.“
temperatur_celsius = 22.5
anzahl_messungen = 17
csv_datei = "daten.csv"
Für Variablen und Funktionen wird normalerweise
snake_case verwendet.
text = "Hallo" # str
zahl = 42 # int
kommazahl = 3.1415 # float
aktiv = True # bool
nichts = None # NoneType
wert = 42
print(type(wert))
Ausgabe:
<class 'int'>
text = "42"
zahl = int(text)
kommazahl = float(text)
neuer_text = str(zahl)
print(zahl + 8)
aktiv = True
fehler = False
if aktiv:
print("System aktiv")
Die Python-Werte heißen exakt True und False,
jeweils mit großem Anfangsbuchstaben.
ergebnis = None
if ergebnis is None:
print("Noch kein Ergebnis vorhanden")
None repräsentiert das Fehlen eines Wertes.
Manche Python-Objekte können nach ihrer Erzeugung verändert werden, andere nicht.
a + b # Addition
a - b # Subtraktion
a * b # Multiplikation
a / b # Division
a // b # Ganzzahldivision
a % b # Rest / Modulo
a ** b # Potenz
print(10 / 3) # 3.333...
print(10 // 3) # 3
print(10 % 3) # 1
print(2 ** 8) # 256
x == 10 # gleich
x != 10 # ungleich
x > 10 # größer
x < 10 # kleiner
x >= 10 # größer oder gleich
x <= 10 # kleiner oder gleich
if alter >= 18 and land == "AT":
print("Bedingungen erfüllt")
if ist_admin or ist_editor:
print("Bearbeitung erlaubt")
if not aktiv:
print("Nicht aktiv")
x = 10
x += 2
x -= 3
x *= 4
x /= 2
a == b # Haben die Objekte denselben Wert?
a is b # Sind es tatsächlich dieselben Objekte?
Für normale Wertevergleiche verwendet man ==.
is wird insbesondere bei None verwendet.
if wert is None:
print("Kein Wert")
Zeichenketten sind Folgen von Zeichen und gehören zu den meistverwendeten Datentypen überhaupt.
text1 = "Hallo"
text2 = 'Python'
vorname = "Max"
nachname = "Mustermann"
name = vorname + " " + nachname
print(name)
name = "Max"
alter = 28
print(f"{name} ist {alter} Jahre alt.")
f-Strings sind meistens die angenehmste Art, Werte in Text einzubauen.
temperatur = 21.5678
print(f"{temperatur:.1f} °C")
print(f"{temperatur:.2f} °C")
Ausgabe:
21.6 °C
21.57 °C
text = " Hallo Python "
print(text.strip())
print(text.lower())
print(text.upper())
print(text.replace("Python", "Welt"))
print(text.startswith(" Hallo"))
print(text.endswith(" "))
daten = "Temperatur;Luftdruck;Feuchtigkeit"
teile = daten.split(";")
print(teile)
woerter = ["Python", "ist", "praktisch"]
satz = " ".join(woerter)
print(satz)
text = """Erste Zeile
Zweite Zeile
Dritte Zeile"""
print(text)
print("Zeile 1\nZeile 2")
print("Name:\tMax")
print("Er sagte: \"Hallo\"")
\n – Zeilenumbruch\t – Tabulator\" – Anführungszeichen\\ – Backslashpfad = r"C:\Users\Max\Documents"
print(pfad)
Das Präfix r verhindert, dass Backslashes als Escape-Sequenzen
interpretiert werden.
Listen speichern mehrere Werte in einer geordneten, veränderbaren Sammlung.
farben = ["rot", "grün", "blau"]
print(farben)
farben = ["rot", "grün", "blau"]
print(farben[0])
print(farben[1])
print(farben[-1])
Der erste Index ist 0. Negative Indizes zählen vom Ende.
farben = ["rot", "grün"]
farben.append("blau")
farben = ["rot"]
farben.extend(["grün", "blau"])
farben = ["rot", "blau"]
farben.insert(1, "grün")
farben = ["rot", "grün", "blau"]
farben.remove("grün")
farben = ["rot", "grün", "blau"]
letztes_element = farben.pop()
print(letztes_element)
farben = ["rot", "grün", "blau"]
print(len(farben))
zahlen = [5, 2, 8, 1]
zahlen.sort()
print(zahlen)
Absteigend:
zahlen.sort(reverse=True)
zahlen = [5, 2, 8, 1]
sortiert = sorted(zahlen)
sort() verändert die vorhandene Liste.
sorted() liefert eine neue Liste zurück.
Tupel ähneln Listen, können nach ihrer Erstellung jedoch nicht verändert werden.
koordinaten = (47.0707, 15.4395)
print(koordinaten[0])
koordinaten = (47.0707, 15.4395)
breitengrad, laengengrad = koordinaten
print(breitengrad)
print(laengengrad)
Tupel eignen sich besonders für zusammengehörige Werte, deren Struktur nicht verändert werden soll, beispielsweise Koordinaten oder RGB-Werte.
Dictionaries speichern Werte als Schlüssel-Wert-Paare. Sie gehören zu den praktischsten Datenstrukturen in Python.
person = {
"name": "Max",
"alter": 28,
"stadt": "Graz"
}
print(person["name"])
print(person.get("alter"))
print(person.get("beruf", "nicht angegeben"))
get() ist praktisch, wenn ein Schlüssel möglicherweise
nicht vorhanden ist.
person["alter"] = 29
person["beruf"] = "Entwickler"
for schluessel, wert in person.items():
print(schluessel, wert)
for schluessel in person:
print(schluessel)
for wert in person.values():
print(wert)
Sets sind ungeordnete Mengen eindeutiger Werte. Doppelte Elemente werden automatisch entfernt.
zahlen = {1, 2, 3, 3, 4}
print(zahlen)
namen = ["Anna", "Max", "Anna", "Peter"]
eindeutig = set(namen)
print(eindeutig)
a = {1, 2, 3}
b = {3, 4, 5}
print(a | b) # Vereinigung
print(a & b) # Schnittmenge
print(a - b) # Differenz
Mit Slicing lassen sich Ausschnitte aus Listen, Strings und anderen Sequenzen gewinnen.
werte = [10, 20, 30, 40, 50]
print(werte[1:4])
Ergebnis:
[20, 30, 40]
Der Startindex wird eingeschlossen, der Endindex nicht.
werte[:3]
werte[2:]
werte[::2]
Nimmt jedes zweite Element.
werte[::-1]
temperatur = 25
if temperatur > 20:
print("Warm")
alter = 17
if alter >= 18:
print("Volljährig")
else:
print("Minderjährig")
temperatur = 18
if temperatur > 25:
print("Warm")
elif temperatur > 15:
print("Mild")
elif temperatur > 5:
print("Kühl")
else:
print("Kalt")
temperatur = 22
sonnig = True
if temperatur > 20 and sonnig:
print("Gutes Wetter")
farben = ["rot", "grün", "blau"]
if "grün" in farben:
print("Grün ist vorhanden")
liste = []
if liste:
print("Liste enthält Werte")
else:
print("Liste ist leer")
Als falsch gelten unter anderem:
FalseNone00.0""[]{}set()alter = 20
status = "volljährig" if alter >= 18 else "minderjährig"
print(status)
Das ist der sogenannte bedingte Ausdruck oder ternäre Ausdruck.
for zahl in range(5):
print(zahl)
Ausgabe: 0 bis 4.
range(5) # 0, 1, 2, 3, 4
range(2, 6) # 2, 3, 4, 5
range(0, 10, 2) # 0, 2, 4, 6, 8
farben = ["rot", "grün", "blau"]
for farbe in farben:
print(farbe)
farben = ["rot", "grün", "blau"]
for index, farbe in enumerate(farben):
print(index, farbe)
Damit erhält man gleichzeitig Index und Wert.
for nummer, farbe in enumerate(farben, start=1):
print(nummer, farbe)
namen = ["Anna", "Max", "Peter"]
alter = [30, 28, 41]
for name, jahre in zip(namen, alter):
print(name, jahre)
zip() verbindet mehrere Sequenzen elementweise.
zaehler = 0
while zaehler < 5:
print(zaehler)
zaehler += 1
Bei while muss sichergestellt sein, dass die Abbruchbedingung
irgendwann erreicht wird. Sonst entsteht eine Endlosschleife.
for zahl in range(100):
if zahl == 10:
break
print(zahl)
break beendet die Schleife vollständig.
for zahl in range(10):
if zahl == 5:
continue
print(zahl)
continue überspringt lediglich den aktuellen Durchlauf.
for zahl in range(5):
if zahl == 10:
break
else:
print("Die Schleife wurde nicht mit break beendet.")
Diese Konstruktion ist weniger bekannt, kann bei Suchvorgängen aber elegant sein.
Comprehensions erzeugen Collections kompakt aus anderen iterierbaren Objekten. Sie sind sehr praktisch, sollten aber lesbar bleiben.
quadrate = [zahl ** 2 for zahl in range(10)]
print(quadrate)
gerade = [
zahl
for zahl in range(20)
if zahl % 2 == 0
]
quadrate = {
zahl: zahl ** 2
for zahl in range(5)
}
reste = {
zahl % 3
for zahl in range(20)
}
Eine einfache Comprehension ist elegant. Eine dreifach verschachtelte Comprehension mit mehreren Bedingungen ist oftmals bloß eine gewöhnliche Schleife im Abendkleid. Lesbarkeit geht vor Kürze.
Funktionen zerlegen Programme in kleinere, wiederverwendbare Einheiten. Gut strukturierter Python-Code besteht normalerweise aus mehreren überschaubaren Funktionen statt aus einem gewaltigen linearen Skript.
def begruessung(name):
print(f"Hallo, {name}!")
begruessung("Max")
def addiere(a, b):
return a + b
ergebnis = addiere(5, 7)
print(ergebnis)
def min_max(werte):
return min(werte), max(werte)
minimum, maximum = min_max([4, 8, 1, 9])
Technisch wird dabei ein Tupel zurückgegeben.
def begruessung(name="Welt"):
print(f"Hallo, {name}!")
begruessung()
begruessung("Max")
def beschreibe(name, alter, stadt):
print(name, alter, stadt)
beschreibe(
stadt="Graz",
name="Max",
alter=28
)
def summiere(*zahlen):
return sum(zahlen)
print(summiere(1, 2, 3, 4, 5))
*args nimmt eine beliebige Anzahl positionsbasierter Argumente entgegen.
def anzeigen(**daten):
for schluessel, wert in daten.items():
print(schluessel, wert)
anzeigen(
name="Max",
alter=28,
stadt="Graz"
)
**kwargs sammelt benannte Argumente in einem Dictionary.
verdoppeln = lambda x: x * 2
print(verdoppeln(5))
Lambdas eignen sich für sehr kleine anonyme Funktionen, beispielsweise als Sortierschlüssel.
personen = [
{"name": "Anna", "alter": 32},
{"name": "Max", "alter": 25}
]
personen.sort(key=lambda person: person["alter"])
def celsius_zu_fahrenheit(celsius):
"""Wandelt Celsius in Fahrenheit um."""
return celsius * 9 / 5 + 32
def funktion():
wert = 10
print(wert)
funktion()
wert existiert in diesem Beispiel nur innerhalb der Funktion.
temperatur = 20
def anzeigen():
print(temperatur)
anzeigen()
zaehler = 0
def erhoehen():
global zaehler
zaehler += 1
Globale Variablen sind gelegentlich nützlich, in größeren Programmen aber häufig ein Zeichen dafür, dass die Struktur verbessert werden könnte.
Fehler gehören zum Programmieren. Entscheidend ist nicht, sie vollständig zu vermeiden, sondern sie kontrolliert zu erkennen und sinnvoll zu behandeln.
try:
zahl = int("abc")
except ValueError:
print("Keine gültige Ganzzahl.")
try:
zahl = int(eingabe)
ergebnis = 100 / zahl
except ValueError:
print("Ungültige Zahl.")
except ZeroDivisionError:
print("Division durch null ist nicht möglich.")
try:
zahl = int("42")
except ValueError:
print("Fehler")
else:
print("Erfolgreich:", zahl)
else wird nur ausgeführt, wenn im try-Block
keine Exception auftritt.
try:
print("Versuch")
finally:
print("Dieser Block läuft immer.")
alter = -5
if alter < 0:
raise ValueError("Das Alter darf nicht negativ sein.")
try:
irgendetwas()
except Exception as fehler:
print(fehler)
Ein allgemeines except Exception kann sinnvoll sein, sollte aber
bewusst eingesetzt werden. Präzise Fehlertypen sind meist besser.
Bei einem unbehandelten Fehler zeigt Python einen sogenannten Traceback an. Besonders wichtig sind:
Der letzte Eintrag des Tracebacks ist meist der beste Ausgangspunkt für die Fehlersuche.
with open("notizen.txt", "r", encoding="utf-8") as datei:
inhalt = datei.read()
print(inhalt)
with open("daten.txt", "r", encoding="utf-8") as datei:
for zeile in datei:
print(zeile.strip())
with open("ausgabe.txt", "w", encoding="utf-8") as datei:
datei.write("Hallo Welt!\n")
"w" überschreibt eine bereits vorhandene Datei.
with open("log.txt", "a", encoding="utf-8") as datei:
datei.write("Neuer Eintrag\n")
r – lesenw – schreiben und überschreibena – anhängenx – neue Datei erzeugen, Fehler falls vorhandenb – Binärmodus
Der with-Block sorgt dafür, dass die Datei zuverlässig geschlossen
wird – auch wenn innerhalb des Blocks ein Fehler auftritt.
Für moderne Python-Programme ist pathlib oft angenehmer und lesbarer als
das manuelle Zusammensetzen von Dateipfaden.
from pathlib import Path
from pathlib import Path
ordner = Path.cwd()
print(ordner)
from pathlib import Path
basisordner = Path(__file__).resolve().parent
print(basisordner)
Das ist besonders nützlich, wenn ein Skript Dateien aus demselben Ordner
wie die .py-Datei verarbeiten soll.
basisordner = Path(__file__).resolve().parent
datei = basisordner / "daten" / "messwerte.csv"
Dadurch muss man sich nicht selbst mit Windows- und Linux-Pfadtrennern herumschlagen.
if datei.exists():
print("Datei vorhanden")
ordner = Path("daten")
for datei in ordner.glob("*.csv"):
print(datei)
for datei in ordner.rglob("*.csv"):
print(datei)
datei = Path("messungen.csv")
print(datei.name)
print(datei.stem)
print(datei.suffix)
Python besitzt mit dem Modul csv bereits in der Standardbibliothek
Werkzeuge zum Lesen und Schreiben von CSV-Dateien.
import csv
with open("daten.csv", "r", encoding="utf-8", newline="") as datei:
reader = csv.reader(datei)
for zeile in reader:
print(zeile)
reader = csv.reader(
datei,
delimiter=";"
)
Gerade deutschsprachige Tabellenkalkulationen verwenden häufig Semikolon statt Komma als Feldtrenner.
import csv
daten = [
["Zeit", "Temperatur"],
["12:00", 21.5],
["13:00", 22.1]
]
with open("ausgabe.csv", "w", encoding="utf-8", newline="") as datei:
writer = csv.writer(datei)
writer.writerows(daten)
import csv
with open("daten.csv", encoding="utf-8", newline="") as datei:
reader = csv.DictReader(datei)
for zeile in reader:
print(zeile["Temperatur"])
DictReader verwendet die Kopfzeile als Schlüssel.
Das macht Code häufig deutlich verständlicher.
from pathlib import Path
ordner = Path(__file__).resolve().parent
dateien = sorted(ordner.glob("*.csv"))
for datei in dateien:
print(datei.name)
JSON ist eines der wichtigsten Austauschformate für strukturierte Daten und wird beispielsweise von Web-APIs, Konfigurationsdateien und vielen Programmen verwendet.
import json
with open("daten.json", "r", encoding="utf-8") as datei:
daten = json.load(datei)
print(daten)
import json
daten = {
"name": "Sensor 1",
"temperatur": 21.7
}
with open("daten.json", "w", encoding="utf-8") as datei:
json.dump(
daten,
datei,
indent=4,
ensure_ascii=False
)
import json
text = '{"name": "Sensor", "wert": 42}'
daten = json.loads(text)
text = json.dumps(
daten,
indent=4,
ensure_ascii=False
)
Python-Programme lassen sich auf mehrere Dateien aufteilen. Eine Python-Datei kann dabei als Modul in eine andere importiert werden.
import math
wurzel = math.sqrt(16)
print(wurzel)
from math import sqrt
print(sqrt(25))
import datetime as dt
jetzt = dt.datetime.now()
Datei berechnungen.py:
def addiere(a, b):
return a + b
Andere Datei:
from berechnungen import addiere
print(addiere(2, 3))
import csv
import json
import math
import random
import statistics
import datetime
import logging
import argparse
import subprocess
import shutil
import re
from pathlib import Path
from modul import *
Diese Schreibweise sollte gewöhnlich vermieden werden, weil nicht mehr klar erkennbar ist, welche Namen aus welchem Modul stammen.
Für ausführbare Python-Skripte ist es gute Praxis, den eigentlichen Programmeinstieg
in eine Funktion namens main() zu legen.
def main():
print("Programm wird ausgeführt.")
if __name__ == "__main__":
main()
Wird die Datei direkt ausgeführt, besitzt __name__ den Wert
"__main__".
Wird dieselbe Datei hingegen importiert, wird main() nicht automatisch
gestartet. Dadurch können Funktionen eines Skripts auch von anderen Programmen
verwendet werden.
Mit Klassen lassen sich Daten und dazugehörige Funktionen zu eigenen Objekttypen zusammenfassen.
class Sensor:
def __init__(self, name, temperatur):
self.name = name
self.temperatur = temperatur
def anzeigen(self):
print(
f"{self.name}: "
f"{self.temperatur} °C"
)
sensor = Sensor("BME280", 21.5)
sensor.anzeigen()
__init__() wird beim Erzeugen eines neuen Objektes ausgeführt
und dient typischerweise dazu, dessen Attribute zu initialisieren.
self bezeichnet das konkrete Objekt, auf dem eine Methode
aufgerufen wird.
self.name
self.temperatur
class Sensor:
def messen(self):
print("Messung")
class Temperatursensor(Sensor):
def temperatur(self):
return 21.5
class Sensor:
def __init__(self, name):
self.name = name
def __str__(self):
return f"Sensor: {self.name}"
sensor = Sensor("BME280")
print(sensor)
Spezielle Methoden mit doppelten Unterstrichen werden manchmal scherzhaft „dunder methods“ genannt.
Nicht jedes Programm benötigt Klassen. Bei kleinen Automatisierungsskripten sind einige klare Funktionen häufig die einfachere und bessere Lösung.
Wenn eine Klasse hauptsächlich Daten speichern soll, reduziert
@dataclass unnötigen Standardcode.
from dataclasses import dataclass
@dataclass
class Messwert:
zeit: str
temperatur: float
luftdruck: float
messung = Messwert(
zeit="12:00",
temperatur=21.5,
luftdruck=1015.2
)
print(messung)
Generatoren erzeugen Werte erst dann, wenn sie benötigt werden. Dadurch können große Datenmengen verarbeitet werden, ohne alles gleichzeitig im Speicher zu halten.
def zahlen_bis(maximum):
zahl = 1
while zahl <= maximum:
yield zahl
zahl += 1
for zahl in zahlen_bis(5):
print(zahl)
quadrate = (
x ** 2
for x in range(1000000)
)
Die runden Klammern erzeugen hier keinen Tupel, sondern einen Generator.
Das bekannte with open(...) ist ein Beispiel für einen Context Manager.
Context Manager verwalten Ressourcen zuverlässig.
with open("daten.txt", encoding="utf-8") as datei:
inhalt = datei.read()
Sobald der Block verlassen wird, räumt der Context Manager die verwendete Ressource automatisch auf.
Python bleibt dynamisch typisiert, kann aber mit Typinformationen versehen werden. Diese erhöhen vor allem bei größeren Projekten die Verständlichkeit.
name: str = "Max"
alter: int = 28
temperatur: float = 21.5
aktiv: bool = True
def addiere(a: int, b: int) -> int:
return a + b
temperaturen: list[float] = [
20.5,
21.2,
19.8
]
def finde_sensor(name: str) -> str | None:
if name == "BME280":
return "gefunden"
return None
Python kontrolliert Type Hints beim normalen Programmablauf nicht automatisch. Sie dienen Dokumentation, IDEs und Werkzeugen zur statischen Codeanalyse.
from datetime import date
heute = date.today()
print(heute)
from datetime import datetime
jetzt = datetime.now()
print(jetzt)
from datetime import datetime
jetzt = datetime.now()
text = jetzt.strftime("%d.%m.%Y %H:%M")
print(text)
from datetime import datetime
text = "18.08.2026"
datum = datetime.strptime(
text,
"%d.%m.%Y"
)
from datetime import date
start = date(2026, 8, 1)
ende = date(2026, 8, 18)
differenz = ende - start
print(differenz.days)
Reguläre Ausdrücke dienen dazu, Text nach Mustern zu durchsuchen oder zu zerlegen.
Python stellt dafür das Modul re bereit.
import re
text = "Temperatur: 21.5 °C"
treffer = re.search(
r"\d+\.\d+",
text
)
if treffer:
print(treffer.group())
import re
text = "Sensor 1, Sensor 2, Sensor 3"
zahlen = re.findall(r"\d+", text)
print(zahlen)
\d # Ziffer
\w # Buchstabe/Ziffer/Unterstrich
\s # Leerraum
. # beliebiges Zeichen
+ # mindestens einmal
* # beliebig oft
? # optional
^ # Textanfang
$ # Textende
muster = r"\d+\.\d+"
Reguläre Ausdrücke werden in Python fast immer als Raw Strings geschrieben.
Eine virtuelle Umgebung isoliert die installierten Python-Pakete eines Projekts vom restlichen System. Das verhindert Versionskonflikte und gehört bei ernsthaften Python-Projekten zur normalen Grundhygiene.
python -m venv .venv
Unter Linux häufig:
python3 -m venv .venv
.venv\Scripts\Activate.ps1
.venv\Scripts\activate.bat
source .venv/bin/activate
deactivate
In die Datei .gitignore gehört normalerweise:
.venv/
Mit pip können zusätzliche Python-Bibliotheken installiert werden,
die nicht Bestandteil der Standardbibliothek sind.
pip install requests
python -m pip install requests
Damit ist eindeutiger, zu welcher Python-Installation der verwendete Paketmanager gehört.
pip list
pip freeze > requirements.txt
pip install -r requirements.txt
pip uninstall paketname
python -m pip install --upgrade paketname
Für Skripte, die Parameter über die Kommandozeile erhalten sollen, bietet Python
das Modul argparse.
import argparse
parser = argparse.ArgumentParser(
description="Verarbeitet eine CSV-Datei."
)
parser.add_argument(
"datei",
help="Pfad zur CSV-Datei"
)
args = parser.parse_args()
print(args.datei)
python programm.py daten.csv
parser.add_argument(
"--ausgabe",
default="ergebnis.csv",
help="Name der Ausgabedatei"
)
Aufruf:
python programm.py daten.csv --ausgabe zusammen.csv
python programm.py --help
argparse erzeugt automatisch eine brauchbare Hilfeseite für das Programm.
print() eignet sich hervorragend für kleine Tests. Bei größeren Programmen
sollte für Status-, Warn- und Fehlermeldungen das Modul logging verwendet werden.
import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)
logging.info("Programm gestartet")
logging.warning("Warnung")
logging.error("Fehler")
DEBUG – detaillierte EntwicklungsinformationenINFO – normale StatusinformationenWARNING – ungewöhnliche SituationERROR – FehlerCRITICAL – schwerwiegender Fehlerlogging.basicConfig(
filename="programm.log",
level=logging.INFO,
encoding="utf-8"
)
Tests prüfen automatisch, ob Funktionen die erwarteten Ergebnisse liefern. Schon wenige Tests können verhindern, dass eine spätere Änderung unbemerkt bestehende Funktionen zerstört.
def addiere(a, b):
return a + b
assert addiere(2, 3) == 5
assert addiere(-1, 1) == 0
import unittest
def addiere(a, b):
return a + b
class TestBerechnungen(unittest.TestCase):
def test_addiere(self):
self.assertEqual(
addiere(2, 3),
5
)
if __name__ == "__main__":
unittest.main()
print("Variable:", wert)
print("Typ:", type(wert))
Für kleine Skripte ist das vollkommen legitim und oft der schnellste Weg.
Entwicklungsumgebungen wie Visual Studio Code erlauben Breakpoints. Das Programm hält an einer bestimmten Zeile an und Variablen können während der Ausführung untersucht werden.
wert = berechne_etwas()
breakpoint()
print(wert)
Python besitzt einen eingebauten Einstiegspunkt für interaktives Debugging.
Python-Skripte können beispielsweise mit PyInstaller in eine unter Windows ausführbare Datei verpackt werden. Dabei wird nicht der Python-Code in klassischen Maschinencode übersetzt; vielmehr werden Interpreter, Programm und benötigte Bestandteile zu einem Paket gebündelt.
python -m pip install pyinstaller
pyinstaller programm.py
pyinstaller --onefile programm.py
pyinstaller --onefile --windowed programm.py
--windowed sollte nur verwendet werden, wenn das Programm
tatsächlich keine Konsole benötigt. Andernfalls verschwinden Fehlermeldungen
scheinbar im Nirwana.
Wird eine EXE per Doppelklick gestartet, kann ihr Arbeitsverzeichnis anders sein, als man beim Start aus Visual Studio Code erwartet.
Statt blind mit relativen Pfaden zu arbeiten, ist es oft sinnvoll, den gewünschten Basisordner ausdrücklich festzulegen.
from pathlib import Path
basisordner = Path(__file__).resolve().parent
Während der Fehlersuche kann am Ende eines kleinen Werkzeugs vorübergehend stehen:
input("Enter drücken zum Beenden...")
Das ist keine elegante Fehlerbehandlung, verhindert beim Testen per Doppelklick aber, dass das Konsolenfenster sofort wieder verschwindet.
# Schlecht:
x = 21.5
d = "messung.csv"
# Besser:
temperatur_celsius = 21.5
eingabedatei = "messung.csv"
Eine Funktion sollte möglichst eine klar umrissene Aufgabe erfüllen. Kann ihre Tätigkeit nicht in einem kurzen Satz beschrieben werden, übernimmt sie möglicherweise zu viele Aufgaben.
Wenn derselbe Code mehrfach kopiert wird, sollte geprüft werden, ob daraus eine Funktion entstehen kann.
# Weniger gut:
if temperatur > 80:
alarm()
# Verständlicher:
MAXIMALE_TEMPERATUR = 80
if temperatur > MAXIMALE_TEMPERATUR:
alarm()
PEP 8 ist der verbreitete Stil-Leitfaden für Python-Code. Zu den bekannten Konventionen gehören:
snake_case für Funktionen und VariablenPascalCase für KlassenDrei zusätzliche verständliche Zeilen sind fast immer besser als ein brillanter Einzeiler, dessen Bedeutung am nächsten Dienstag niemand mehr rekonstruieren möchte.
x = 5 # Zuweisung
x == 5 # Vergleich
farben = ["rot", "grün", "blau"]
print(farben[0]) # rot
for zahl in range(1, 5):
print(zahl)
Ergebnis:
1
2
3
4
Der Endwert 5 gehört nicht mehr zum Bereich.
alter = 28
# Fehler:
# print("Alter: " + alter)
# Richtig:
print("Alter: " + str(alter))
# Noch besser:
print(f"Alter: {alter}")
alter = input("Alter: ")
print(type(alter))
Für Berechnungen daher beispielsweise:
alter = int(input("Alter: "))
a = [1, 2, 3]
b = a
b.append(4)
print(a)
a und b verweisen hier auf dieselbe Liste.
Für eine flache Kopie:
b = a.copy()
# Problematisch:
def hinzufuegen(wert, liste=[]):
liste.append(wert)
return liste
Besser:
def hinzufuegen(wert, liste=None):
if liste is None:
liste = []
liste.append(wert)
return liste
# Eher vermeiden:
pfad = "daten/" + dateiname
# Besser:
from pathlib import Path
pfad = Path("daten") / dateiname
# Schlecht:
try:
etwas()
except:
pass
Damit verschwinden unter Umständen echte Programmfehler völlig lautlos.
# Ungünstig:
list = [1, 2, 3]
str = "Hallo"
file = "daten.txt"
Dadurch überschreibt man Namen eingebauter Python-Funktionen oder etabliert unnötig verwirrende Bezeichnungen.
Sobald ein Python-Projekt über ein einzelnes Skript hinauswächst, sollte der Quellcode sinnvoll aufgeteilt werden.
mein_projekt/
│
├── main.py
├── daten.py
├── utils.py
├── requirements.txt
├── README.md
├── .gitignore
│
├── daten/
│ └── messungen.csv
│
└── tests/
└── test_daten.py
Beispielsweise:
main.py – Programmeinstiegdaten.py – Einlesen und Speichernsensor.py – Sensorlogikutils.py – Hilfsfunktionentests/ – automatisierte TestsTypische Einträge:
.venv/
__pycache__/
*.pyc
dist/
build/
*.spec
temperatur_celsius ist wesentlich aussagekräftiger als x.
pathlib für Dateipfade.
Das erspart zahlreiche Probleme zwischen Windows, Linux und Raspberry Pi.
with open(...) beim Dateizugriff.
Dateien werden dadurch zuverlässig geschlossen.
encoding="utf-8" an.
Umlaute sollen schließlich kein Abenteuer sein.
requirements.txt oder eine moderne Projektkonfiguration
macht ein Projekt reproduzierbar.
except: löst Fehler nicht – es versteckt sie.
print() für schnelle Experimente.
Bei dauerhaften Anwendungen ist logging jedoch die robustere Lösung.
enumerate(), wenn du Index und Element benötigst.
Manuelles Hochzählen eines Index ist meist unnötig.
zip(), wenn mehrere Sequenzen gemeinsam verarbeitet werden.
x2_temp_final_new für einen brillanten Variablennamen gehalten hast.
Das folgende Beispiel verbindet mehrere der zuvor behandelten Konzepte:
Funktionen, pathlib, CSV-Verarbeitung, Fehlerbehandlung,
Logging und einen sauberen Programmeinstieg.
import csv
import logging
from pathlib import Path
logging.basicConfig(
level=logging.INFO,
format="%(levelname)s: %(message)s"
)
def finde_csv_dateien(ordner: Path) -> list[Path]:
"""Findet alle CSV-Dateien im angegebenen Verzeichnis."""
return sorted(ordner.glob("*.csv"))
def zeige_dateien(dateien: list[Path]) -> None:
"""Gibt die gefundenen Dateien aus."""
for nummer, datei in enumerate(dateien, start=1):
print(f"{nummer}: {datei.name}")
def zaehle_zeilen(datei: Path) -> int:
"""Zählt die Datenzeilen einer CSV-Datei."""
with datei.open(
"r",
encoding="utf-8",
newline=""
) as csv_datei:
reader = csv.reader(csv_datei)
# Kopfzeile überspringen
next(reader, None)
return sum(1 for _ in reader)
def main() -> None:
ordner = Path(__file__).resolve().parent
logging.info(
"Suche CSV-Dateien in %s",
ordner
)
dateien = finde_csv_dateien(ordner)
if not dateien:
logging.warning(
"Keine CSV-Dateien gefunden."
)
return
zeige_dateien(dateien)
for datei in dateien:
try:
anzahl = zaehle_zeilen(datei)
except (OSError, UnicodeError) as fehler:
logging.error(
"Fehler bei %s: %s",
datei.name,
fehler
)
continue
print(
f"{datei.name}: "
f"{anzahl} Datenzeilen"
)
if __name__ == "__main__":
main()
Bereits dieses kleine Beispiel zeigt einen wichtigen Unterschied zwischen bloß „funktionierendem Code“ und brauchbarem Programmcode: Die einzelnen Aufgaben sind getrennt, Fehler werden kontrolliert behandelt, Pfade werden sauber bestimmt und der Programmablauf bleibt nachvollziehbar.
Wer die Inhalte dieser Seite beherrscht, besitzt bereits ein solides Fundament. Ab diesem Punkt hängt der weitere Lernweg vor allem davon ab, wofür Python eingesetzt werden soll.
pathlibshutilsubprocess# Ausgabe
print("Hallo")
# Variable
name = "Max"
# Bedingung
if name == "Max":
print("Gefunden")
# Liste
werte = [1, 2, 3]
# Schleife
for wert in werte:
print(wert)
# Funktion
def verdoppeln(wert):
return wert * 2
# Dictionary
person = {
"name": "Max",
"alter": 28
}
# Fehlerbehandlung
try:
zahl = int("42")
except ValueError:
print("Fehler")
# Datei lesen
with open(
"daten.txt",
encoding="utf-8"
) as datei:
text = datei.read()
# Pfade
from pathlib import Path
ordner = Path(__file__).resolve().parent
# Dateien suchen
dateien = sorted(
ordner.glob("*.csv")
)
# sauberer Programmeinstieg
def main():
print("Start")
if __name__ == "__main__":
main()
Python lernt man nicht dadurch, dass man jede Methode auswendig kennt. Entscheidend ist, die grundlegenden Konzepte zu verstehen und zu wissen, welche Werkzeuge existieren. Den exakten Funktionsnamen kann man nachschlagen; ein sauberes gedankliches Modell des Programms hingegen nicht.