Pakete#

Code in Dateien, Module und Pakete aufteilen#

Größere Programme enthalten oft dutzende Klassen mit hunderten Funktionen und vielen tausend Zeilen Code. Hier wird es sehr schnell schwer einen Überblick zu behalten, wenn alle Klassen in einer Datei definiert sind. Insbesondere wenn verschiedene Programmierer an verschiedenen Stellen im Programm arbeiten, kommt es dann sehr schnell zu Versionskonflikten, wenn Leute an ähnlichen Dateien arbeiten.

Um dies organisiert und übersichtlich zu halten, wird Code in mehrere Dateien mit der Erweiterung .py aufgespalten. Dabei ist es üblich jeweils eine Datei

  • pro Klasse, wenn Klassen definiert werden

  • pro Thema, wenn Hilfsfunktionen definiert werden (z.B. Mathematik-Funktionen, …)

  • pro Aufgabenbereich, wenn (z.B. Laden von Daten getrennt von deren Verarbeitung. So kann man z.B. später andere Verarbeitungsschritte definieren und das Laden wiederverwenden)

Speichern wir jede Klasse der Geometrieelemente aus dem Teil der Klassendefinition aus der letzten Vorlesung so hätten wir dann z.B. eine Projektstruktur entsprechend:

Dabei enthält jede Datei nur den Code der gleichnamigen Klasse, auch wenn dies nur wenige Zeilen sind, wie im Fall der Klassen Triangle, Tetragon und Pentagon. Entscheidend ist, dass wenn ein Programmierer nach dem Code für eine Klasse sucht, er genau sieht in welcher Datei dieser zu finden ist und nicht groß suchen muss.

Noch größere Projekte spalten man in mehrere Module indem man weitere Unterverzeichnisse anlegt. So wollen wir z.B. alle generischen Klassen für Punkte in das Verzeichnis points gruppieren und alle geometrischen Formen in das Verzeichnis shapes. So lassen sich größere Projekte gut strukturieren.

Die Summe aller Module formt dann ein Package. In diesem Fall das Package geometry, welches wir in verschiedenen Implementierungen wieder verwenden können.

main() - Der Startpunkt eines Programmes#

Wenn Code über mehrere Dateien verteilt ist, braucht Python einen Hinweis welcher Code ausgeführt werden soll. Hierfür definiert man die spezielle Einstiegsfunktion main(). Sie gibt es in fast allen Programmiersprachen und gibt immer den Startpunkt eines Programms an.

In Python hat sie entweder keine Argumente oder sie erhält diese dynamisch, wenn sie vom Nutzer / von einem anderen Programm aufgerufen wird (a.k.a. Kommandozeilenargumente).

def main():
	print("This is the main function")

Allerdings möchte man vermeiden, dass die Funktion main() auch aufgerufen wird, wenn die Python-Datei zum Beispiel als Bibliothek eingebunden wird, wo man nur an den Funktionen interessiert ist. Deshalb nutzt man am Ende einer Datei mit einer main()-Funktion die folgende Verzweigung.

if __name__ == "__main__":
	main()
This is the main function

Sie nutzt aus, dass der Wert der Standardvariable __name__ in der Hauptdatei immer '__main__' lautet. Während sie in einer importierten Datei den Namen der Hauptdatei angibt.

Importieren von Modulen#

Um zu vermeiden, dass ständig unnötiger Code geladen wird lädt Python diesen Code nicht automatisch. Wollen wir also den Code in unseren Dateien, Modulen und Packages nutzen so müssen wir vorher Python anweisen diesen zu laden. Dieses Importieren weist man mit dem Befehl import an.

Ein einfacher Import ist der import ganzer Pakete. Dies geschieht, indem wir import und dem Paketnamen schreiben.

import geometry.points.ImmutablePoint
import geometry.shapes.Line

def main():
	point_1 = geometry.points.ImmutablePoint.ImmutablePoint(x=54.083336, y=12.108811)
	point_2 = geometry.points.ImmutablePoint.ImmutablePoint(y=12.094167, x=54.075211)
	linie_1 = geometry.shapes.Line.Line(start=point_1, end=point_2)
	print(f"Die Länge der Linie zwischen Punkt 1 und 2 ist: {linie_1.length()}")

if __name__ == "__main__":
	main()
Die Länge der Linie zwischen Punkt 1 und 2 ist: 0.016747010509340444

Der Nachteil des Imports ganzer Pakete ist, dass wenn wir hieraus einzelne Klassen referenzieren wollen, die sich in Untermodulen befinden, so müssen wir den kompletten Pfad der Klasse angeben. In dem Beispiel oben zum Beispiel geometry.points.ImmutablePoint.ImmutablePoint.

Deshalb importiert man meist einzelne Module indem man den Pfad eines Moduls angibt, wie zum Beispiel geometry.points.ImmutablePoint.ImmutablePoint. Hierbei kann man den importierten Modulen auch neue Namen geben wie point oder line in dem Beispiel unten.

import geometry.points.ImmutablePoint as point
import geometry.shapes.Line as line

def main():
	point_1 = point.ImmutablePoint(x=54.083336, y=12.108811)
	point_2 = point.ImmutablePoint(y=12.094167, x=54.075211)
	linie_1 = line.Line(start=point_1, end=point_2)
	print(f"Die Länge der Linie zwischen Punkt 1 und 2 ist: {linie_1.length()}")

if __name__ == "__main__":
	main()
Die Länge der Linie zwischen Punkt 1 und 2 ist: 0.016747010509340444

Alternativ lassen sich auch Teile eines Moduls mit dem Platzhalter * und dem Befehl from importieren. Alle Elemente werden mit dem Platzhalter * importiert. Spezifische Elemente wie einzelne Klassen können auch direkt angegeben werden, wie im folgenden Beispiel Line.

from geometry.points.ImmutablePoint import *
from geometry.shapes.Line import Line

def main():
	point_1 = ImmutablePoint(x=54.083336, y=12.108811)
	point_2 = ImmutablePoint(y=12.094167, x=54.075211)
	linie_1 = Line(start=point_1, end=point_2)
	print(f"Die Länge der Linie zwischen Punkt 1 und 2 ist: {linie_1.length()}")

if __name__ == "__main__":
	main()
Die Länge der Linie zwischen Punkt 1 und 2 ist: 0.016747010509340444

Standard Paktete aus Python importieren#

Python beinhaltet viele Standardpakete für typische Aufgaben. Für die Bau- und Umweltinformatik sind die folgenden am sinnvollsten:

packet

description

collections

Mehr komplexe Datentypen zum zählen, sortieren

http

Funktionen des HTTP-Internetprotokolls wie Web-Server

json

Funktionen um Objekte als Text abzuspeichern

logging

Funktionen um Logs zu schreiben

math

Mathematische Funktionen

os

Funktionen um Dateien zu finden, laden und speichern

pickle

Funktionen um Objekte binär abzuspeichern

pprint

print-Funktionen um Objekte schöner (pretty) auszugeben

random

Funktionen zum Erzeugen von Zufallszahlen

re

Funktionen für Reguläre Ausdrücke um Text zu suchen

sys

Funktionen um Systeminformationen zu erhalten

time

Funktionen für Zeit und Datumsangaben

timeit

Funktionen um die Performance von Funktionen zu testen

traceback

Funktionen um den Stack aufzulisten

urllib

Funktionen um ULRs im Internet zu laden und verarbeiten

Von der Liste haben wir die Bibliotheken math, time, timeit, traceback und logging schon kennen gelernt und benutzt. Die anderen Pakete bieten allerdings weitere sinnvolle Funktionen.

Wollen wir zum Beispiel alle Dateien in einem Verzeichnis auflisten, so nutzen wir das Paket os.

import os

folder = "geometry/shapes/"
for count, filename in enumerate(os.listdir(folder)):
	if os.path.isfile(os.path.join(folder, filename)):
		path = os.path.join(folder, filename)
		print(path)
geometry/shapes/Triangle.py
geometry/shapes/Pentagon.py
geometry/shapes/Polygon.py
geometry/shapes/Line.py
geometry/shapes/Tetragon.py

Viele Webseiten bieten Programmierschnittstellen an, so genannte APIs, da diese APIs auch von den eigenen Webseiten genutzt werden, um Daten nachzuladen, die auf der Webseite angezeigt werden. Die APIs nutzen meist das JSON-Format um Daten auszutauschen. Dies ist ein Text-basiertes Dateiformat, das in Python sehr stark dem dict-Datentyp ähnelt, aber auch alle anderen primitiven und zusammengesetzten Datentypen von Python unterstützt.

Wir möchten zum Beispiel die Wetterdaten einer Wetterstation in Deutschland analysieren. Diese Daten bekommen wir beim Deutschen Wetterdiest. Diese Daten kann man sich auch von der API herunterladen. Hierfür braucht man die ID (Identifikationsnummer) einer Wetterstation welche hier zu finden ist. Wir nehmen als Beispiel eine Station im Hansaviertel in Rostock mit der ID 12495.

Dann kann man die Wetterdaten mit Python mit Hilfe des Paketes urllib von der API laden. Das JSON-Format können wir mit dem json Paket verarbeiten. Wir laden dazu zuerst vom Deutschen Wetterdienst ein binäres Datenpaket vom Datentype bytes. Dieses konvertieren wir mit der Funktion loads aus dem json Paket in ein Python dict. Um das schöner lesbar auszugeben, nutzen wir die Funktion pprint aus dem Paket pprint (pretty-print).

import urllib.request
import json
import pprint

stationID='12495' # Rostock-Hansaviertel
with urllib.request.urlopen(f'https://dwd.api.proxy.bund.dev/v30/stationOverviewExtended?stationIds={stationID}') as f:
    data=f.read() # Dies gibt uns ein binären Datentyp zurück
    wetter=json.loads(data) # Wir konvertieren den binären Datentyp in ein dict
    pprint.pprint(wetter, indent=2, compact=True)
{ '12495': { 'days': [ { 'dayDate': '2025-05-02',
                         'icon': 3,
                         'icon1': None,
                         'icon2': None,
                         'moonPhase': 1,
                         'moonrise': 1746166041000,
                         'moonriseOnThisDay': 1746166041000,
                         'moonset': 1746230309000,
                         'moonsetOnThisDay': 1746230309000,
                         'precipitation': 16,
                         'stationId': None,
                         'sunrise': 1746154870000,
                         'sunriseOnThisDay': 1746154870000,
                         'sunset': 1746208488000,
                         'sunsetOnThisDay': 1746208488000,
                         'sunshine': 32767,
                         'temperatureMax': 220,
                         'temperatureMin': 52,
                         'windDirection': 2010,
                         'windGust': 296,
                         'windSpeed': 93},
                       { 'dayDate': '2025-05-03',
                         'icon': 27,
                         'icon1': None,
                         'icon2': None,
                         'moonPhase': 1,
                         'moonrise': 1746257259000,
                         'moonriseOnThisDay': 1746257259000,
                         'moonset': 1746318351000,
                         'moonsetOnThisDay': None,
                         'precipitation': 48,
                         'stationId': None,
                         'sunrise': 1746241161000,
                         'sunriseOnThisDay': 1746241161000,
                         'sunset': 1746294983000,
                         'sunsetOnThisDay': 1746294983000,
                         'sunshine': 32767,
                         'temperatureMax': 227,
                         'temperatureMin': 133,
                         'windDirection': 2640,
                         'windGust': 370,
                         'windSpeed': 130},
                       { 'dayDate': '2025-05-04',
                         'icon': 19,
                         'icon1': None,
                         'icon2': None,
                         'moonPhase': 1,
                         'moonrise': 1746348565000,
                         'moonriseOnThisDay': 1746348565000,
                         'moonset': 1746318351000,
                         'moonsetOnThisDay': 1746318351000,
                         'precipitation': 38,
                         'stationId': None,
                         'sunrise': 1746327455000,
                         'sunriseOnThisDay': 1746327455000,
                         'sunset': 1746381478000,
                         'sunsetOnThisDay': 1746381478000,
                         'sunshine': 32767,
                         'temperatureMax': 158,
                         'temperatureMin': 80,
                         'windDirection': 2990,
                         'windGust': 445,
                         'windSpeed': 204},
                       { 'dayDate': '2025-05-05',
                         'icon': 3,
                         'icon1': None,
                         'icon2': None,
                         'moonPhase': 2,
                         'moonrise': 1746439694000,
                         'moonriseOnThisDay': 1746439694000,
                         'moonset': 1746405884000,
                         'moonsetOnThisDay': 1746405884000,
                         'precipitation': 0,
                         'stationId': None,
                         'sunrise': 1746413750000,
                         'sunriseOnThisDay': 1746413750000,
                         'sunset': 1746467972000,
                         'sunsetOnThisDay': 1746467972000,
                         'sunshine': 32767,
                         'temperatureMax': 104,
                         'temperatureMin': 52,
                         'windDirection': 40,
                         'windGust': 296,
                         'windSpeed': 130},
                       { 'dayDate': '2025-05-06',
                         'icon': 3,
                         'icon1': None,
                         'icon2': None,
                         'moonPhase': 2,
                         'moonrise': 1746530594000,
                         'moonriseOnThisDay': 1746530594000,
                         'moonset': 1746493121000,
                         'moonsetOnThisDay': 1746493121000,
                         'precipitation': 0,
                         'stationId': None,
                         'sunrise': 1746500047000,
                         'sunriseOnThisDay': 1746500047000,
                         'sunset': 1746554468000,
                         'sunsetOnThisDay': 1746554468000,
                         'sunshine': 32767,
                         'temperatureMax': 120,
                         'temperatureMin': 40,
                         'windDirection': 40,
                         'windGust': 278,
                         'windSpeed': 111},
                       { 'dayDate': '2025-05-07',
                         'icon': 2,
                         'icon1': None,
                         'icon2': None,
                         'moonPhase': 2,
                         'moonrise': 1746621298000,
                         'moonriseOnThisDay': 1746621298000,
                         'moonset': 1746580205000,
                         'moonsetOnThisDay': 1746580205000,
                         'precipitation': 0,
                         'stationId': None,
                         'sunrise': 1746586345000,
                         'sunriseOnThisDay': 1746586345000,
                         'sunset': 1746640963000,
                         'sunsetOnThisDay': 1746640963000,
                         'sunshine': 32767,
                         'temperatureMax': 128,
                         'temperatureMin': 44,
                         'windDirection': 3410,
                         'windGust': 370,
                         'windSpeed': 148},
                       { 'dayDate': '2025-05-08',
                         'icon': 3,
                         'icon1': None,
                         'icon2': None,
                         'moonPhase': 2,
                         'moonrise': 1746711890000,
                         'moonriseOnThisDay': 1746711890000,
                         'moonset': 1746667210000,
                         'moonsetOnThisDay': 1746667210000,
                         'precipitation': 0,
                         'stationId': None,
                         'sunrise': 1746672645000,
                         'sunriseOnThisDay': 1746672645000,
                         'sunset': 1746727458000,
                         'sunsetOnThisDay': 1746727458000,
                         'sunshine': 32767,
                         'temperatureMax': 112,
                         'temperatureMin': 41,
                         'windDirection': 3440,
                         'windGust': 315,
                         'windSpeed': 130},
                       { 'dayDate': '2025-05-09',
                         'icon': 2,
                         'icon1': None,
                         'icon2': None,
                         'moonPhase': 3,
                         'moonrise': 1746802461000,
                         'moonriseOnThisDay': 1746802461000,
                         'moonset': 1746754194000,
                         'moonsetOnThisDay': 1746754194000,
                         'precipitation': 0,
                         'stationId': None,
                         'sunrise': 1746758946000,
                         'sunriseOnThisDay': 1746758946000,
                         'sunset': 1746813952000,
                         'sunsetOnThisDay': 1746813952000,
                         'sunshine': 32767,
                         'temperatureMax': 114,
                         'temperatureMin': 32,
                         'windDirection': 390,
                         'windGust': 315,
                         'windSpeed': 111},
                       { 'dayDate': '2025-05-10',
                         'icon': 3,
                         'icon1': None,
                         'icon2': None,
                         'moonPhase': 3,
                         'moonrise': 1746893091000,
                         'moonriseOnThisDay': 1746893091000,
                         'moonset': 1746841213000,
                         'moonsetOnThisDay': 1746841213000,
                         'precipitation': 0,
                         'stationId': None,
                         'sunrise': 1746845249000,
                         'sunriseOnThisDay': 1746845249000,
                         'sunset': 1746900446000,
                         'sunsetOnThisDay': 1746900446000,
                         'sunshine': 32767,
                         'temperatureMax': 133,
                         'temperatureMin': 38,
                         'windDirection': 300,
                         'windGust': 333,
                         'windSpeed': 111},
                       { 'dayDate': '2025-05-11',
                         'icon': 2,
                         'icon1': None,
                         'icon2': None,
                         'moonPhase': 3,
                         'moonrise': 1746983828000,
                         'moonriseOnThisDay': 1746983828000,
                         'moonset': 1746928322000,
                         'moonsetOnThisDay': 1746928322000,
                         'precipitation': 0,
                         'stationId': None,
                         'sunrise': 1746931553000,
                         'sunriseOnThisDay': 1746931553000,
                         'sunset': 1746986939000,
                         'sunsetOnThisDay': 1746986939000,
                         'sunshine': 32767,
                         'temperatureMax': 138,
                         'temperatureMin': 58,
                         'windDirection': 3330,
                         'windGust': 333,
                         'windSpeed': 130}],
             'forecast1': { 'cloudCoverTotal': [],
                            'dewPoint2m': [ 76, 79, 77, 80, 78, 79, 81, 82, 88,
                                            95, 102, 107, 110, 113, 116, 115,
                                            117, 122, 124, 124, 125, 125, 127,
                                            127, 125, 126, 128, 125, 124, 124,
                                            122, 122, 126, 128, 127, 126, 123,
                                            119, 117, 109, 96, 94, 84, 72, 67,
                                            64, 61, 56, 51, 48, 44],
                            'humidity': [ 582, 617, 621, 654, 671, 689, 707,
                                          712, 727, 715, 698, 664, 621, 569,
                                          546, 517, 505, 515, 535, 558, 612,
                                          664, 753, 798, 818, 850, 890, 889,
                                          901, 925, 924, 931, 943, 925, 878,
                                          839, 813, 781, 766, 745, 692, 683,
                                          647, 604, 603, 630, 672, 722, 735,
                                          775, 780],
                            'icon': [ 32767, 1, 32767, 32767, 32767, 32767,
                                      32767, 2, 32767, 32767, 32767, 32767,
                                      32767, 3, 32767, 32767, 32767, 32767,
                                      32767, 4, 32767, 32767, 3, 3, 3, 2, 3, 3,
                                      4, 3, 3, 3, 3, 2, 2, 2, 3, 3, 3, 3, 3, 3,
                                      27, 27, 27, 27, 27, 19, 19, 18, 18, 18,
                                      18, 4, 18, 18, 19, 19, 19, 19, 19, 19, 4,
                                      3, 3, 3, 3, 3, 2, 2, 1, 1, 1],
                            'icon1h': [ 3, 3, 3, 2, 3, 3, 4, 3, 3, 3, 3, 2, 2,
                                        2, 3, 3, 3, 3, 3, 3, 27, 27, 27, 27, 27,
                                        19, 19, 18, 18, 18, 18, 4, 18, 18, 19,
                                        19, 19, 19, 19, 19, 4, 3, 3, 3, 3, 3, 2,
                                        2, 1, 1, 1],
                            'isDay': [ False, False, False, False, False, False,
                                       False, True, False, False, False, False,
                                       False, True, False, False, False, False,
                                       False, False, False, False, False, False,
                                       False, False, False, False, False, False,
                                       True, True, True, True, True, True, True,
                                       True, True, True, True, True, True, True,
                                       True, False, False, False, False, False,
                                       False, False, False, False, True, True,
                                       True, True, True, True, True, True, True,
                                       True, True, True, True, True, True,
                                       False, False, False, False],
                            'precipitationProbablity': None,
                            'precipitationProbablityIndex': None,
                            'precipitationTotal': [ 32767, 32767, 32767, 32767,
                                                    32767, 32767, 32767, 32767,
                                                    32767, 32767, 32767, 32767,
                                                    32767, 32767, 32767, 32767,
                                                    32767, 32767, 32767, 32767,
                                                    32767, 32767, 0, 0, 0, 0, 0,
                                                    0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                    0, 0, 0, 0, 0, 0, 6, 9, 12,
                                                    4, 5, 6, 6, 5, 5, 3, 3, 0,
                                                    2, 2, 2, 3, 3, 3, 4, 3, 0,
                                                    0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                    0],
                            'start': 1746136800000,
                            'stationId': '12495',
                            'sunshine': [ 32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767],
                            'surfacePressure': [ 10120, 10119, 10115, 10112,
                                                 10113, 10110, 10108, 10108,
                                                 10108, 10108, 10108, 10104,
                                                 10101, 10100, 10093, 10088,
                                                 10082, 10075, 10069, 10066,
                                                 10064, 10064, 10061, 10060,
                                                 10057, 10055, 10047, 10041,
                                                 10035, 10027, 10022, 10016,
                                                 10013, 10010, 10010, 10015,
                                                 10020, 10027, 10036, 10039,
                                                 10046, 10050, 10053, 10057,
                                                 10061, 10066, 10075, 10082,
                                                 10089, 10093, 10098],
                            'temperature': [ 32767, 32767, 52, 32767, 32767,
                                             32767, 32767, 32767, 118, 32767,
                                             32767, 32767, 32767, 32767, 202,
                                             32767, 32767, 32767, 32767, 32767,
                                             173, 32767, 32767, 158, 152, 149,
                                             144, 138, 135, 133, 133, 136, 146,
                                             157, 170, 184, 201, 211, 219, 225,
                                             227, 223, 216, 202, 189, 171, 162,
                                             156, 151, 146, 143, 140, 136, 134,
                                             133, 135, 140, 147, 153, 155, 157,
                                             158, 154, 152, 152, 150, 148, 143,
                                             133, 120, 104, 96, 85, 80, 74, 68,
                                             65, 61, 59, 62, 69, 76, 81, 87, 91,
                                             96, 99, 101, 104, 104, 102, 99, 91,
                                             80, 70, 63, 56, 52, 48, 44, 41, 40,
                                             44, 48, 58, 73, 84, 94, 103, 108,
                                             113, 117, 120, 120, 120, 115, 107,
                                             93, 80, 73, 65, 58, 52, 47, 45, 44,
                                             45, 49, 61, 78, 93, 101, 111, 117,
                                             120, 124, 127, 126, 128, 122, 110,
                                             95, 81, 72, 65, 58, 53, 50, 45, 41,
                                             41, 45, 53, 65, 81, 92, 98, 103,
                                             108, 111, 112, 111, 111, 105, 97,
                                             83, 71, 63, 57, 52, 47, 39, 35, 32,
                                             34, 43, 53, 68, 87, 98, 103, 107,
                                             110, 113, 114, 113, 112, 107, 97,
                                             87, 73, 68, 64, 59, 55, 52, 45, 39,
                                             38, 46, 55, 72, 82, 99, 108, 115,
                                             124, 130, 133, 131, 127, 122, 115,
                                             102, 92, 83, 78, 74, 71, 67, 62,
                                             58, 58, 64, 72, 84, 104, 112, 119,
                                             126, 132, 137, 138, 138, 138, 133,
                                             120, 109, 98, 89, 83, 79],
                            'temperatureStd': [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                0, 13, 12, 10, 9, 11, 12, 10, 9,
                                                12, 11, 12, 12, 12, 13, 14, 14,
                                                16, 15, 16, 17, 17, 15, 14, 14,
                                                14, 13, 13, 13, 14, 13, 12, 11,
                                                12, 9, 14, 14, 14, 15, 16, 16,
                                                16, 16, 16, 16, 15, 14, 12, 13,
                                                14, 14, 13, 12, 13, 14, 14, 16,
                                                16, 13, 14, 15, 15, 16, 17, 17,
                                                18, 18, 17, 16, 15, 15, 14, 14,
                                                15, 16, 16, 16, 16, 16, 16, 18,
                                                16, 14, 15, 16, 16, 17, 17, 18,
                                                18, 19, 19, 19, 17, 17, 15, 14,
                                                14, 15, 14, 15, 14, 15, 15, 15,
                                                15, 14, 15, 17, 17, 17, 19, 19,
                                                17, 18, 18, 19, 20, 18, 17, 16,
                                                17, 17, 17, 17, 16, 16, 17, 18,
                                                18, 16, 16, 18, 17, 17, 18, 18,
                                                19, 19, 20, 20, 20, 18, 16, 16,
                                                16, 16, 16, 18, 18, 18, 19, 19,
                                                17, 17, 19, 20, 19, 19, 21, 22,
                                                22, 22, 22, 22, 21, 22, 19, 19,
                                                20, 20, 20, 18, 17, 18, 18, 20,
                                                20, 17, 18, 20, 20, 21, 20, 18,
                                                18, 19, 20, 20, 19, 18, 17, 17,
                                                18, 17, 18, 16, 17, 17, 19, 16,
                                                17, 16, 17, 20, 20, 22, 22, 23,
                                                23, 24, 23, 23, 23, 21, 19, 18,
                                                19, 19, 19],
                            'timeStep': 3600000,
                            'windDirection': None,
                            'windGust': None,
                            'windSpeed': None},
             'forecast2': { 'cloudCoverTotal': [],
                            'dewPoint2m': [ 37, 35, 35, 29, 21, 17, 19, 12, 4,
                                            10, 19, 19, 21, 20, 19, 13, 9, 12,
                                            22, 17, 10, 7, 8, 7, 4, 6, 15, 8,
                                            -1, 1, 6, 2, -5, 3, 11, 5, 4, 7, 18,
                                            18, 17, 24, 35, 32, 30, 29, 36, 33,
                                            30, 39, 50, 41, 38, 39, 41, 39],
                            'humidity': [ 823, 828, 727, 630, 564, 567, 700,
                                          754, 768, 764, 636, 542, 507, 521,
                                          654, 728, 775, 770, 612, 503, 448,
                                          453, 600, 697, 747, 758, 631, 517,
                                          457, 485, 633, 701, 751, 752, 589,
                                          493, 467, 500, 681, 750, 820, 856,
                                          722, 567, 497, 530, 680, 752, 800,
                                          840, 692, 562, 509, 529, 676, 758],
                            'icon': [ 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
                                      3, 2, 1, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2, 3,
                                      3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2,
                                      3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2,
                                      2],
                            'icon1h': [ 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
                                        3, 3, 2, 1, 2, 2, 2, 3, 3, 2, 2, 2, 2,
                                        2, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 2,
                                        2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2,
                                        2, 2, 2, 2],
                            'isDay': [ False, False, True, True, True, True,
                                       True, False, False, False, True, True,
                                       True, True, True, False, False, False,
                                       True, True, True, True, True, False,
                                       False, False, True, True, True, True,
                                       True, False, False, False, True, True,
                                       True, True, True, False, False, False,
                                       True, True, True, True, True, False,
                                       False, False, True, True, True, True,
                                       True, False],
                            'precipitationProbablity': None,
                            'precipitationProbablityIndex': None,
                            'precipitationTotal': [ 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                    0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                    0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                    0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                    0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                    0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                    0, 0],
                            'start': 1746396000000,
                            'stationId': '12495',
                            'sunshine': [ 32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767, 32767, 32767, 32767, 32767,
                                          32767],
                            'surfacePressure': [ 10110, 10125, 10138, 10149,
                                                 10146, 10149, 10157, 10161,
                                                 10157, 10152, 10153, 10142,
                                                 10132, 10132, 10143, 10152,
                                                 10153, 10157, 10173, 10156,
                                                 10154, 10154, 10167, 10173,
                                                 10171, 10164, 10158, 10152,
                                                 10152, 10150, 10156, 10160,
                                                 10165, 10169, 10176, 10172,
                                                 10172, 10177, 10190, 10201,
                                                 10204, 10209, 10214, 10207,
                                                 10205, 10204, 10209, 10207,
                                                 10208, 10206, 10207, 10207,
                                                 10197, 10192, 10201, 10205],
                            'temperature': [],
                            'temperatureStd': [],
                            'timeStep': 10800000,
                            'windDirection': None,
                            'windGust': None,
                            'windSpeed': None},
             'forecastStart': None,
             'threeHourSummaries': None,
             'warnings': []}}

Externe Pakete installieren und importieren#

Die Stärke von Python ist allerdings die riesige Auswahl an vorhandenen Paketen. Für die meisten Anwendungszwecke gibt es entsprechende Python Packages. Ein solches Verzeichnis is PyPi das über 400.000 Pakete listet.

Die Installation neuer Pakete für Python ist einfach. Hierfür öffnet man ein Terminal (Kommandozeile) und gibt den Befehl pip install <packetname> ein.

Zum Beispiel wollen wir die eben geladenen Wetterdaten anzeigen. Hierfür nutzen wir:

  • zuerst das Paket pandas zum Erzeugen einer Tabelle aus den Wetterdaten.

  • dann nutzen wir das Paket plotly zum Zeichnen eines Diagramms.

  • zuletzt erzeugen wir uns einen Webserver mit dash der uns das Diagramm immer anzeigt

Alles drei installieren wir mit pip. Wir können das in einem Aufruf machen. Wir nutzen den --quiet Switch, um die Ausgabe zu reduzieren.

pip install pandas plotly dash  --quiet
Note: you may need to restart the kernel to use updated packages.

Jetzt laden wir beide Pakete, wobei man üblicher Weise pandas die Abkürzung pd zuweist und Plotly Express, welches einfach zu bedienen ist, die Abkürzung px.

import pandas as pd
import plotly.express as px
import dash

Nun wandeln wir die tageweise Wettervorhersage days der Daten von der Wetterstation mit der stationID zuerst in eine Tabelle um, da diese von Plotly express verarbeitet werden kann. Tabellen heißen in Pandas DataFrames (allgemein werden so Tabellen in der Data Science genannt). Wir erzeugen also aus der Wettervorhersage ein neue Objektinstanz vom Typ DataFrame via

df = pd.DataFrame(wetter[stationID]['days'])
df
stationId dayDate temperatureMin temperatureMax precipitation windSpeed windGust windDirection sunshine sunrise ... moonrise moonset moonriseOnThisDay moonsetOnThisDay sunriseOnThisDay sunsetOnThisDay moonPhase icon icon1 icon2
0 None 2025-05-02 52 220 16 93 296 2010 32767 1746154870000 ... 1746166041000 1746230309000 1746166041000 1.746230e+12 1746154870000 1746208488000 1 3 None None
1 None 2025-05-03 133 227 48 130 370 2640 32767 1746241161000 ... 1746257259000 1746318351000 1746257259000 NaN 1746241161000 1746294983000 1 27 None None
2 None 2025-05-04 80 158 38 204 445 2990 32767 1746327455000 ... 1746348565000 1746318351000 1746348565000 1.746318e+12 1746327455000 1746381478000 1 19 None None
3 None 2025-05-05 52 104 0 130 296 40 32767 1746413750000 ... 1746439694000 1746405884000 1746439694000 1.746406e+12 1746413750000 1746467972000 2 3 None None
4 None 2025-05-06 40 120 0 111 278 40 32767 1746500047000 ... 1746530594000 1746493121000 1746530594000 1.746493e+12 1746500047000 1746554468000 2 3 None None
5 None 2025-05-07 44 128 0 148 370 3410 32767 1746586345000 ... 1746621298000 1746580205000 1746621298000 1.746580e+12 1746586345000 1746640963000 2 2 None None
6 None 2025-05-08 41 112 0 130 315 3440 32767 1746672645000 ... 1746711890000 1746667210000 1746711890000 1.746667e+12 1746672645000 1746727458000 2 3 None None
7 None 2025-05-09 32 114 0 111 315 390 32767 1746758946000 ... 1746802461000 1746754194000 1746802461000 1.746754e+12 1746758946000 1746813952000 3 2 None None
8 None 2025-05-10 38 133 0 111 333 300 32767 1746845249000 ... 1746893091000 1746841213000 1746893091000 1.746841e+12 1746845249000 1746900446000 3 3 None None
9 None 2025-05-11 58 138 0 130 333 3330 32767 1746931553000 ... 1746983828000 1746928322000 1746983828000 1.746928e+12 1746931553000 1746986939000 3 2 None None

10 rows × 21 columns

Nun plotten wir die Daten df als LinienDiagramm mit Hilfe von Plotly wobei wir als x-Axe das Datum wählen (dayDate) und als y-Axe die minimale Temperatur temperatureMin und maximale Temperatur temperatureMax.

fig=px.line(df, x="dayDate", y=["temperatureMin", "temperatureMax"])
fig.show(renderer="svg")
../_images/3e6f190522e81588a85d7c7a11a983739649782d052f17cced2ed80c87df5771.svg

Zuletzt wollen wir dieses Diagramm in einer Webseite auf einem Webserver anzeigen. Hier nutzen wir das Paket dash welches erlaubt eine Webseite mit Python-Befehlen zu erzeugen und darin interaktive Diagramme von Plotly mit anzuzeigen.

import dash

app = dash.Dash()

Dann erzeugen wir eine Webseite mit einer Überschrift (H1), welche den Plot als Graph enthält.

app.layout = dash.html.Div(children = [
    dash.html.H1(children='Wetter in Rostock'),
    dash.dcc.Graph(id="fare_vs_age", figure=fig)
])

Und starten den Webserver.

app.run_server()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[16], line 1
----> 1 app.run_server()

File /opt/hostedtoolcache/Python/3.11.0/x64/lib/python3.11/site-packages/jupyter_dash/jupyter_app.py:176, in JupyterDash.run_server(self, mode, width, height, inline_exceptions, **kwargs)
    154 """
    155 Serve the app using flask in a background thread. You should not run this on a
    156 production server, use gunicorn/waitress instead.
   (...)    173     ``Dash.run_server`` method.
    174 """
    175 # Get superclass run_server method
--> 176 super_run_server = super(JupyterDash, self).run_server
    178 if not JupyterDash._in_ipython:
    179     # If not in IPython context, call run run_server synchronously
    180     super_run_server(**kwargs)

AttributeError: 'super' object has no attribute 'run_server'

Dies startet einen Webserver auf den wir in einem Browser unter http://127.0.0.1:8083/ zugreifen können. Er zeigt uns eine Webseite mit einem interaktiven Diagramm welches die Wetterdaten anzeigt.