Python Threading: So einfach macht man einen Thread

Threads sind eine tolle Sache, insbesondere auf Multi-Core Prozessoren wie dem Raspberry Pi 2. Läuft ohne Thread das Programm strikt von oben nach unten, ohne eine Unterbrechung (von Interrups einmal abgesehen), kann man mit Threads Teile seines Programms gleichzeitig ausführen lassen.

Wozu könnte man einen Thread gebrauchen?

Beispielsweise wenn man an einem Raspberry Pi mehrere Sensoren gleichzeitig auslesen möchte oder mehrere LEDs gleichzeitig, aber voneinander unabhängig steuern möchte.

In meinem Beispiel lasse ich eine LED blinken, während ein Temperatursensor ausgelesen wird. Diese Aufgabe klingt lächerlich simpel, doch versucht das mal ohne Threads in einem einzigen Programm! Also: Ein Thread muss her.

Ein Thread in Python ist ähnlich aufgebaut wie eine Klasse, von der eine Funktion aufgerufen wird – nur mit Zusatz-Zeug. Der Code um den Thread zu machen ist in Python allerdings extrem einfach und leicht zu verstehen. Folgender Code implementiert den Thread und man kann ihn dann jederzeit im Programm starten:

import threading

class Blinker(threading.Thread):
def __init__(self, dur, color):
⇥⇥ threading.Thread.__init__(self)
⇥⇥ self.dur = dur
⇥⇥ self.color = color
⇥⇥ self.daemon = True
⇥⇥ self.start()

def run(self):
⇥⇥ blink(self.dur, self.color)

(Die weißen ⇥ Zeichen im Code bitte durch [TAB] oder je zwei Leerzeichen ersetzen. Braun ist der Konstruktor, Grün ist die Funktion des Threads)

Wie man den Thread programmiert

Man erstellt eine Klasse, welche threading.Thread erbt. Ein Thread muss immer einen Konstruktor haben, welcher das Thread-Objekt „baut“. Dies wird mit def __init__(self) gemacht. Self muss immer drinstehen, sonst geht es nicht. Wenn der Thread noch Argumente mitbekommen soll, kann dies hinter self geschrieben werden. In meinem Fall gebe ich ihm noch einen Int dur (wie lang soll die LED blinken) und einen string color (in welcher Farbe soll die LED blinken) mit. Die übergebenen Argumente werden dann im Konstruktor in das Objekt geschrieben  (self.dur = dur, etc).

self.darmon = True bedeutet: Wenn das eigentliche Programm beendet wird, wird der Thread auch beendet. Mit self.start() wird der Thread automatisch gestartet (siehe run).

Der Konstruktor hat nun das Thread Objekt gebaut, und die Funktion def run(self) gestartet. In diese Funktion kann man jetzt schreiben, was der Thread denn eigentlich machen soll. Bei mir steht einfach nur die Funktion blink() drin, mehr nicht.

Der Thread ist fertig und funktioniert?

Jetzt muss man ihn nur noch im Programm starten! Dazu gibt es zwei Möglichkeiten. Entweder ruft man ihn einfach auf (in meinem Fall Blinker(3, red)) – dies hat zur Folge, dass er im Hintergrund läuft aber man keine Kontrolle mehr über den Thread hat. Daher ist es besser, ihn wie folgt aufzurufen: t1 = Blinker(3, red)

In diesem Fall zeigt t1 auf den Thread und man kann so später im Programm warten, bis der Thread fertig ist oder man könnte ihn manuell beenden. Wenn man das eigentliche Programm später pausieren lassen möchte, bis der Thread fertig ist (hier nach 3 Sekunden), tippt man einfach t1.join() an der gewünschten Stelle ein.

Easy!

So einfach macht man Threads! Natürlich ist das nur ein kleiner Überblick, aber mehr habe ich bisher am Raspberry Pi auch nie gebraucht. Zum Schluss noch die Elemente, welche für den Thread notwendig sind, zusammengefasst:

Thread-python-RaspberryPi

Threads laufen NICHT auf mehreren CPU-Kernen!

So praktisch ein Thread auch ist, leider verteilt das Betriebssystem einzelne Threads nicht auf mehrere Prozessor(kerne). Wer seine „Threads“ auf mehrere CPU Kerne verteilen möchte, der muss dafür die Bibliothek multiprocessing in Python verwenden. Dies funktioniert ähnlich wie die Bibliothek threading, jedoch hat jeder Thread einen eigenen Speicherbereich und wird von verschiedenen Prozessorkernen ausgeführt.

Diese Seite Teilen: