Module und Packages in Python
Lerne, wie du Python-Code mit Modulen und Packages organisierst -- von import-Anweisungen ueber eigene Module bis hin zu professionellen Package-Strukturen.
Was sind Module?
Ein Modul in Python ist ganz einfach eine .py-Datei. Jede Python-Datei, die du erstellst, ist automatisch ein Modul. Module helfen dir, deinen Code zu organisieren und wiederzuverwenden.
# Die Datei mathe_helfer.py ist ein Modul namens "mathe_helfer"
# Die Datei utils.py ist ein Modul namens "utils"
# Die Datei main.py ist ein Modul namens "main"
Warum Module?
- Organisation: Code in logische Einheiten aufteilen
- Wiederverwendung: Einmal schreiben, ueberall nutzen
- Namensraeume: Namenskonflikte vermeiden
- Zusammenarbeit: Verschiedene Entwickler arbeiten an verschiedenen Modulen
Die import-Anweisung
Mit import laedt Python ein Modul, damit du seine Funktionen, Klassen und Variablen nutzen kannst.
Ganzes Modul importieren
import math
print(math.pi) # 3.141592653589793
print(math.sqrt(16)) # 4.0
print(math.ceil(4.2)) # 5
print(math.floor(4.8)) # 4
Beim Import eines ganzen Moduls musst du immer den Modulnamen als Praefix verwenden (math.sqrt). Das ist wie ein Nachname — es macht klar, woher die Funktion kommt.
Mehrere Module importieren
import math
import random
import os
# Jedes Modul in einer eigenen Zeile -- das ist die empfohlene Schreibweise!
# Funktioniert auch, ist aber NICHT empfohlen:
import math, random, os
from ... import ... Syntax
Wenn du nur bestimmte Teile eines Moduls brauchst, kannst du sie direkt importieren:
from math import sqrt, pi
# Jetzt ohne Praefix nutzbar:
print(sqrt(25)) # 5.0
print(pi) # 3.141592653589793
Alles importieren mit * (vermeiden!)
from math import *
# Jetzt ist ALLES aus math direkt verfuegbar
print(sin(0)) # 0.0
print(cos(0)) # 1.0
Warnung:
from modul import *ist schlechter Stil! Du weisst nicht mehr, woher welche Funktion kommt, und es kann zu Namenskonflikten fuehren. Verwende es hoechstens in interaktiven Python-Sitzungen.
import ... as ... — Aliase
Manchmal sind Modulnamen lang oder du willst sie abkuerzen:
import datetime as dt
import collections as col
heute = dt.datetime.now()
zaehler = col.Counter([1, 2, 2, 3, 3, 3])
Das ist besonders beliebt bei Data-Science-Bibliotheken:
import numpy as np # Fast jeder nutzt "np"
import pandas as pd # Fast jeder nutzt "pd"
import matplotlib.pyplot as plt # Fast jeder nutzt "plt"
Du kannst auch einzelne Imports umbenennen:
from datetime import datetime as DatumZeit
jetzt = DatumZeit.now()
print(jetzt)
Eigene Module erstellen
Ein eigenes Modul zu erstellen ist kinderleicht — du schreibst einfach eine Python-Datei!
Schritt 1: Modul erstellen
Erstelle eine Datei rechner.py:
# rechner.py -- Unser eigenes Modul
def addieren(a, b):
"""Addiert zwei Zahlen."""
return a + b
def subtrahieren(a, b):
"""Subtrahiert b von a."""
return a - b
def multiplizieren(a, b):
"""Multipliziert zwei Zahlen."""
return a * b
def dividieren(a, b):
"""Dividiert a durch b."""
if b == 0:
raise ValueError("Division durch Null ist nicht erlaubt!")
return a / b
PI = 3.14159265
VERSION = "1.0"
Schritt 2: Modul verwenden
Erstelle eine Datei main.py im gleichen Ordner:
# main.py
import rechner
ergebnis = rechner.addieren(5, 3)
print(f"5 + 3 = {ergebnis}")
ergebnis = rechner.dividieren(10, 3)
print(f"10 / 3 = {ergebnis:.2f}")
print(f"PI = {rechner.PI}")
print(f"Version: {rechner.VERSION}")
Oder mit from ... import:
# main.py
from rechner import addieren, multiplizieren, PI
print(addieren(10, 20)) # 30
print(multiplizieren(4, 5)) # 20
print(PI) # 3.14159265
Das __name__ == "__main__" Pattern
Das ist eines der wichtigsten Patterns in Python. Wenn du es verstehst, verstehst du, wie Python Module ausfuehrt.
Das Problem
Stell dir vor, du hast ein Modul rechner.py mit Testcode:
# rechner.py
def addieren(a, b):
return a + b
def subtrahieren(a, b):
return a - b
# Testcode
print("Test: 5 + 3 =", addieren(5, 3))
print("Test: 10 - 4 =", subtrahieren(10, 4))
Wenn jetzt jemand import rechner in einem anderen Skript macht, wird der Testcode sofort ausgefuehrt — das will man nicht!
Die Loesung
# rechner.py
def addieren(a, b):
return a + b
def subtrahieren(a, b):
return a - b
if __name__ == "__main__":
# Dieser Code wird NUR ausgefuehrt, wenn rechner.py
# DIREKT gestartet wird (python rechner.py)
print("Test: 5 + 3 =", addieren(5, 3))
print("Test: 10 - 4 =", subtrahieren(10, 4))
Wie funktioniert das?
Python setzt die spezielle Variable __name__ automatisch:
- Wird die Datei direkt ausgefuehrt (
python rechner.py):__name__ist"__main__" - Wird die Datei importiert (
import rechner):__name__ist"rechner"(der Modulname)
# demo.py
print(f"Mein __name__ ist: {__name__}")
# Ausfuehren mit: python demo.py
# Ausgabe: Mein __name__ ist: __main__
# Importieren in einem anderen Skript:
# import demo
# Ausgabe: Mein __name__ ist: demo
Typische Verwendung
# textanalyse.py
def woerter_zaehlen(text):
"""Zaehlt die Woerter in einem Text."""
return len(text.split())
def zeichen_zaehlen(text):
"""Zaehlt die Zeichen in einem Text (ohne Leerzeichen)."""
return len(text.replace(" ", ""))
def analyse(text):
"""Gibt eine vollstaendige Textanalyse zurueck."""
return {
"woerter": woerter_zaehlen(text),
"zeichen": zeichen_zaehlen(text),
"saetze": text.count(".") + text.count("!") + text.count("?")
}
if __name__ == "__main__":
# Testcode -- nur bei direkter Ausfuehrung
test_text = "Hallo Welt! Python ist toll. Oder?"
ergebnis = analyse(test_text)
print(f"Woerter: {ergebnis['woerter']}")
print(f"Zeichen: {ergebnis['zeichen']}")
print(f"Saetze: {ergebnis['saetze']}")
Was sind Packages?
Ein Package ist ein Ordner mit Python-Modulen. Der Ordner muss eine spezielle Datei namens __init__.py enthalten (die kann leer sein).
mein_projekt/
main.py
mein_package/
__init__.py
modul_a.py
modul_b.py
helfer/
__init__.py
text_helfer.py
mathe_helfer.py
Warum Packages?
- Struktur: Grosse Projekte brauchen Ordnung
- Namensraeume:
mein_package.modul_aundanderes_package.modul_akoennen koexistieren - Verteilung: Packages lassen sich einfach teilen und installieren
Package-Struktur erstellen
Schritt 1: Ordnerstruktur anlegen
werkzeuge/
__init__.py
text.py
mathe.py
zufall.py
Schritt 2: Module mit Inhalt fuellen
# werkzeuge/text.py
def gross_schreiben(text):
"""Macht den ersten Buchstaben jedes Wortes gross."""
return text.title()
def umkehren(text):
"""Kehrt einen Text um."""
return text[::-1]
def zaehle_vokale(text):
"""Zaehlt die Vokale in einem Text."""
vokale = "aeiouAEIOU"
return sum(1 for zeichen in text if zeichen in vokale)
# werkzeuge/mathe.py
def durchschnitt(zahlen):
"""Berechnet den Durchschnitt einer Zahlenliste."""
if not zahlen:
return 0
return sum(zahlen) / len(zahlen)
def ist_primzahl(n):
"""Prueft, ob eine Zahl eine Primzahl ist."""
if n < 2:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False
return True
# werkzeuge/__init__.py
# Diese Datei macht den Ordner zum Package.
# Sie kann leer sein oder Imports enthalten:
from .text import gross_schreiben, umkehren
from .mathe import durchschnitt, ist_primzahl
__version__ = "1.0.0"
Schritt 3: Package verwenden
# main.py (im uebergeordneten Ordner)
# Wegen __init__.py koennen wir direkt importieren:
from werkzeuge import gross_schreiben, ist_primzahl
print(gross_schreiben("hallo welt")) # Hallo Welt
print(ist_primzahl(17)) # True
# Oder das ganze Package:
import werkzeuge
print(werkzeuge.__version__) # 1.0.0
# Oder ein bestimmtes Modul:
from werkzeuge.text import zaehle_vokale
print(zaehle_vokale("Hallo")) # 2
Relative Imports
Innerhalb eines Packages kannst du relative Imports verwenden. Der Punkt (.) steht fuer das aktuelle Package:
# werkzeuge/zufall.py
# Relative Imports (innerhalb des gleichen Packages)
from .mathe import ist_primzahl
from .text import umkehren
# Ein Punkt = aktuelles Package
# Zwei Punkte = uebergeordnetes Package
import random
def zufalls_primzahl(maximum=100):
"""Gibt eine zufaellige Primzahl zurueck."""
primzahlen = [n for n in range(2, maximum) if ist_primzahl(n)]
return random.choice(primzahlen)
def zufalls_wort_umkehren(woerter):
"""Kehrt ein zufaellig gewaehltes Wort um."""
wort = random.choice(woerter)
return umkehren(wort)
Wichtig: Relative Imports funktionieren nur innerhalb von Packages. In einem Skript, das direkt ausgefuehrt wird (
python skript.py), kannst du sie nicht verwenden.
dir() und help() zum Erkunden
Python hat eingebaute Funktionen, um Module zu erkunden:
dir() — Was steckt drin?
import math
# Zeige alle Namen im Modul
print(dir(math))
# ['__doc__', '__name__', ..., 'ceil', 'cos', 'exp', 'floor', 'log', 'pi', 'sin', 'sqrt', ...]
# Nur die "oeffentlichen" Namen anzeigen (ohne __)
import math
oeffentlich = [name for name in dir(math) if not name.startswith("_")]
print(oeffentlich)
# ['acos', 'acosh', 'asin', ..., 'sqrt', 'tan', 'tanh', 'tau', 'trunc']
help() — Dokumentation anzeigen
import math
help(math.sqrt)
# Help on built-in function sqrt in module math:
# sqrt(x, /)
# Return the square root of x.
# Hilfe fuer das ganze Modul
help(math)
Uebersicht wichtiger Standardmodule
Python kommt mit einer riesigen Standardbibliothek — “Batteries included”! Hier die wichtigsten Module:
| Modul | Beschreibung | Beispiel |
|---|---|---|
math | Mathematische Funktionen | math.sqrt(16) |
random | Zufallszahlen | random.randint(1, 10) |
datetime | Datum und Zeit | datetime.datetime.now() |
os | Betriebssystem-Interaktion | os.listdir(".") |
pathlib | Moderne Pfadoperationen | Path("datei.txt").exists() |
json | JSON lesen/schreiben | json.loads('{"a": 1}') |
csv | CSV-Dateien | csv.reader(datei) |
re | Regulaere Ausdruecke | re.findall(r"\d+", text) |
collections | Spezielle Datenstrukturen | Counter(liste) |
sys | Systemparameter | sys.argv |
argparse | Kommandozeilen-Argumente | Parser erstellen |
itertools | Iterator-Werkzeuge | itertools.combinations() |
functools | Funktions-Werkzeuge | functools.lru_cache |
string | String-Konstanten | string.ascii_letters |
Praxis: Eigenes Utility-Package
Erstelle ein nuetzliches Utility-Package fuer deine Projekte:
meine_utils/
__init__.py
validierung.py
formatierung.py
# meine_utils/validierung.py
import re
def ist_email(text):
"""Prueft, ob ein Text eine gueltige E-Mail-Adresse ist."""
muster = r'^[\w.+-]+@[\w-]+\.[\w.-]+$'
return bool(re.match(muster, text))
def ist_telefonnummer(text):
"""Prueft, ob ein Text eine deutsche Telefonnummer sein koennte."""
bereinigt = text.replace(" ", "").replace("-", "").replace("/", "")
return bereinigt.startswith(("0", "+49")) and bereinigt.lstrip("+").isdigit()
def ist_nicht_leer(text):
"""Prueft, ob ein Text nicht leer ist (nach strip)."""
return bool(text and text.strip())
def ist_zahl(text):
"""Prueft, ob ein Text eine Zahl darstellt."""
try:
float(text)
return True
except ValueError:
return False
# meine_utils/formatierung.py
def als_waehrung(betrag, waehrung="EUR"):
"""Formatiert einen Betrag als Waehrung."""
symbole = {"EUR": "EUR", "USD": "$", "GBP": "£"}
symbol = symbole.get(waehrung, waehrung)
return f"{betrag:,.2f} {symbol}".replace(",", "X").replace(".", ",").replace("X", ".")
def als_prozent(wert, nachkommastellen=1):
"""Formatiert einen Wert als Prozent."""
return f"{wert * 100:.{nachkommastellen}f}%"
def kuerze_text(text, max_laenge=50):
"""Kuerzt einen Text auf die angegebene Laenge."""
if len(text) <= max_laenge:
return text
return text[:max_laenge - 3] + "..."
# meine_utils/__init__.py
from .validierung import ist_email, ist_telefonnummer, ist_nicht_leer, ist_zahl
from .formatierung import als_waehrung, als_prozent, kuerze_text
__version__ = "1.0.0"
__author__ = "Dein Name"
# main.py -- Das Package verwenden
from meine_utils import ist_email, als_waehrung, kuerze_text
# Validierung
print(ist_email("anna@example.com")) # True
print(ist_email("nicht-gueltig")) # False
# Formatierung
print(als_waehrung(1234.50)) # 1.234,50 EUR
print(als_waehrung(99.99, "USD")) # 99,99 $
# Text kuerzen
langer_text = "Dies ist ein sehr langer Text, der gekuerzt werden soll."
print(kuerze_text(langer_text, 30)) # Dies ist ein sehr langer T...
Uebungen
Uebung 1: Eigenes Modul
Erstelle ein Modul temperatur.py mit Funktionen zur Temperaturumrechnung:
# temperatur.py
def celsius_zu_fahrenheit(celsius):
"""Rechnet Celsius in Fahrenheit um."""
return celsius * 9 / 5 + 32
def fahrenheit_zu_celsius(fahrenheit):
"""Rechnet Fahrenheit in Celsius um."""
return (fahrenheit - 32) * 5 / 9
def celsius_zu_kelvin(celsius):
"""Rechnet Celsius in Kelvin um."""
return celsius + 273.15
def kelvin_zu_celsius(kelvin):
"""Rechnet Kelvin in Celsius um."""
return kelvin - 273.15
if __name__ == "__main__":
print(f"100°C = {celsius_zu_fahrenheit(100)}°F")
print(f"212°F = {fahrenheit_zu_celsius(212)}°C")
print(f"0°C = {celsius_zu_kelvin(0)}K")
Uebung 2: Import-Varianten testen
Probiere alle Import-Varianten mit dem random-Modul aus:
# Variante 1: Ganzes Modul
import random
print(random.randint(1, 100))
# Variante 2: Bestimmte Funktionen
from random import randint, choice
print(randint(1, 100))
print(choice(["Apfel", "Birne", "Kirsche"]))
# Variante 3: Mit Alias
import random as rnd
print(rnd.random())
Uebung 3: Package-Struktur
Erstelle die folgende Package-Struktur und fuelle sie mit sinnvollem Code:
spiele/
__init__.py
wuerfel.py # wuerfeln(), mehrfach_wuerfeln()
muenze.py # werfen(), mehrfach_werfen()
karten.py # mischen(), ziehen()
# spiele/wuerfel.py
import random
def wuerfeln(seiten=6):
"""Wuerfelt einmal mit einem Wuerfel."""
return random.randint(1, seiten)
def mehrfach_wuerfeln(anzahl=2, seiten=6):
"""Wuerfelt mehrfach und gibt die Ergebnisse als Liste zurueck."""
return [wuerfeln(seiten) for _ in range(anzahl)]
if __name__ == "__main__":
print(f"Ein Wurf: {wuerfeln()}")
print(f"Drei Wuerfe: {mehrfach_wuerfeln(3)}")
Pro-Tipp: Die richtige Import-Reihenfolge
In professionellen Python-Projekten gibt es eine klare Konvention fuer die Reihenfolge von Imports (definiert in PEP 8):
# 1. Standardbibliothek
import os
import sys
from datetime import datetime
# 2. Drittanbieter-Packages (pip install ...)
import requests
import numpy as np
# 3. Eigene Module/Packages
from mein_package import mein_modul
from .helfer import formatiere
Jede Gruppe wird durch eine Leerzeile getrennt. Innerhalb jeder Gruppe sortierst du alphabetisch. Tools wie isort erledigen das automatisch fuer dich. Diese Ordnung mag pedantisch wirken, macht aber bei groesseren Projekten einen riesigen Unterschied in der Lesbarkeit.