Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
| modul:m323:learningunits:lu03:callbacks [2024/09/11 09:06] – [Asynchron Programmieren in Python] kmaurizi | modul:m323:learningunits:lu03:callbacks [2026/09/08 08:34] (aktuell) – Animation zur Umkehrung der Kontrolle eingebettet admin | ||
|---|---|---|---|
| Zeile 3: | Zeile 3: | ||
| Callback Funktionen sind eine klassische Anwendung von First-Class- und Higher-Order-Functions. | Callback Funktionen sind eine klassische Anwendung von First-Class- und Higher-Order-Functions. | ||
| + | ===== Animation: das Konzept hinter Callbacks ===== | ||
| + | |||
| + | Der erste Tab zeigt das Muster ohne jedes Framework: Ihre Funktion weiss, **was** geschehen soll, die fremde Funktion bestimmt, **wann** und **wie oft**. Man sieht die Übergabe nach unten und den Rückruf nach oben – und dass ein anderer Callback das Verhalten ändert, ohne dass am fremden Code etwas angepasst wird. Die beiden weiteren Tabs zeigen dasselbe Muster in echt: beim Button-Klick (samt dem Klammernfehler weiter unten) und beim nebenläufigen Warten. | ||
| + | |||
| + | {{url> | ||
| ===== Callbacks in der GUI Programmierung ===== | ===== Callbacks in der GUI Programmierung ===== | ||
| Zeile 35: | Zeile 40: | ||
| In diesem Beispiel ist '' | In diesem Beispiel ist '' | ||
| + | |||
| + | <WRAP center round tip 60%> | ||
| + | Achten Sie auf '' | ||
| + | |||
| + | Die beiden letzten Schritte im zweiten Tab der Animation oben zeigen genau diesen Fall. | ||
| + | </ | ||
| ==== Fazit ==== | ==== Fazit ==== | ||
| Zeile 41: | Zeile 52: | ||
| ===== Callbacks in der Asynchronen Programmierung ===== | ===== Callbacks in der Asynchronen Programmierung ===== | ||
| + | |||
| + | <WRAP center round info 60%> | ||
| + | Wir werden das asynchrone Programmieren nicht vertiefen am BZZ. Dies dürfen Sie dann an der Fachhochschule 😉 | ||
| + | </ | ||
| + | |||
| Asynchrone Programmierung ist ein Ansatz, bei dem Operationen ausgeführt werden können, ohne den Ablauf des gesamten Programms zu blockieren. Ein häufiges Szenario für asynchrone Aufrufe sind Netzwerkanfragen, | Asynchrone Programmierung ist ein Ansatz, bei dem Operationen ausgeführt werden können, ohne den Ablauf des gesamten Programms zu blockieren. Ein häufiges Szenario für asynchrone Aufrufe sind Netzwerkanfragen, | ||
| Zeile 66: | Zeile 82: | ||
| * **'' | * **'' | ||
| - | === Beispiele === | ||
| - | == Einfaches | + | === Beispiel: Parallele Ausführung von Aufgaben === |
| + | Eine der Hauptvorteile von asynchroner Programmierung ist die Fähigkeit, mehrere Aufgaben parallel auszuführen, | ||
| - | Ein einfaches Beispiel für die Verwendung von '' | + | <code python> |
| + | import asyncio | ||
| + | |||
| + | async def task_1(): | ||
| + | print('Task 1 gestartet') | ||
| + | await asyncio.sleep(2) | ||
| + | print(' | ||
| + | |||
| + | async def task_2(): | ||
| + | print('Task 2 gestartet') | ||
| + | await asyncio.sleep(3) | ||
| + | print('Task 2 abgeschlossen') | ||
| + | |||
| + | async def main(): | ||
| + | | ||
| + | |||
| + | if __name__ == '__main__': | ||
| + | asyncio.run(main()) | ||
| + | </ | ||
| + | |||
| + | Die Ausgabe zeigt, worum es geht – **beide** Tasks starten, bevor einer davon fertig ist: | ||
| + | |||
| + | < | ||
| + | Task 1 gestartet | ||
| + | Task 2 gestartet | ||
| + | Task 1 abgeschlossen | ||
| + | Task 2 abgeschlossen | ||
| + | </ | ||
| + | |||
| + | Das ganze Programm dauert 3 Sekunden statt 5, weil die beiden Wartezeiten sich überlappen. Der dritte Tab der Animation oben zeigt diesen Ablauf auf einer Zeitachse, mit der sequenziellen Variante als Vergleich. | ||
| + | |||
| + | === Beispiel: Asynchrone Dateioperation === | ||
| + | |||
| + | In diesem Beispiel zeigen wir, wie Dateioperationen asynchron ablaufen können. Das Beispiel liest den Inhalt von zwei Dateien asynchron. | ||
| <code python> | <code python> | ||
| + | import aiofiles | ||
| import asyncio | import asyncio | ||
| - | async def say_hello(): | + | async def read_file(file_name): |
| - | print(" | + | |
| - | await asyncio.sleep(1) | + | contents = await file.read() |
| - | print(" | + | |
| - | | + | |
| + | async def main(): | ||
| + | await asyncio.gather( | ||
| + | read_file(' | ||
| + | | ||
| + | | ||
| if __name__ == ' | if __name__ == ' | ||
| - | asyncio.run(say_hello()) | + | asyncio.run(main()) |
| </ | </ | ||
| - | In diesem | + | === Beispiel: API-Call |
| - | == Beispiel mit API-Call == | + | Ein häufiges Problem bei Netzwerkanfragen ist die Notwendigkeit, |
| - | Dieses Beispiel ruft Daten von einer Dummy-API ab und verwendet | + | Der Mock-Server antwortet erst nach 3 Sekunden ('' |
| <code python> | <code python> | ||
| Zeile 97: | Zeile 153: | ||
| async def fetch_data(): | async def fetch_data(): | ||
| async with httpx.AsyncClient() as client: | async with httpx.AsyncClient() as client: | ||
| - | response = await client.get(' | + | |
| - | | + | |
| + | | ||
| + | except httpx.RequestError as exc: | ||
| + | print(f' | ||
| + | # Ausgabe: An error occurred while requesting data: ReadTimeout | ||
| async def main(): | async def main(): | ||
| - | | + | await fetch_data() |
| - | | + | |
| - | | + | |
| if __name__ == ' | if __name__ == ' | ||
| asyncio.run(main()) | asyncio.run(main()) | ||
| - | | + | </ |
| + | <WRAP center round tip 60%> | ||
| + | Zwei Details, die leicht übersehen werden: | ||
| + | |||
| + | * '' | ||
| + | * Bei einem Timeout ist '' | ||
| + | |||
| + | Setzt man '' | ||
| + | </ | ||
| + | |||
| + | === Beispiel: Daten von mehreren APIs gleichzeitig abrufen === | ||
| + | |||
| + | Hier zeigen wir, wie mehrere API-Aufrufe parallel ablaufen können, um die Effizienz zu verbessern. | ||
| + | |||
| + | <code python> | ||
| + | import httpx | ||
| + | import asyncio | ||
| + | |||
| + | |||
| + | async def fetch_data(url): | ||
| + | async with httpx.AsyncClient() as client: | ||
| + | response = await client.get(url) | ||
| + | return response.text | ||
| + | |||
| + | |||
| + | async def main(): | ||
| + | urls = [ | ||
| + | ' | ||
| + | ' | ||
| + | ] | ||
| + | results = await asyncio.gather(*(fetch_data(url) for url in urls)) | ||
| + | for result in results: | ||
| + | print(result) | ||
| + | |||
| + | |||
| + | if __name__ == ' | ||
| + | asyncio.run(main()) | ||
| </ | </ | ||
| + | Diese Beispiele zeigen verschiedene nützliche Anwendungsfälle für die asynchrone Programmierung in Python. Besonders bei I/ | ||
| ---- | ---- | ||
| - | {{tag> | + | {{tag> |
| - | [[https:// | + | [[https:// |