Lassen Sie uns die aufregende Welt der Coroutinen und der strukturierten Parallelität in Python erkunden. Diese leistungsstarken Funktionen haben die Art und Weise, wie wir gleichzeitigen Code schreiben, revolutioniert und ihn effizienter und einfacher zu verwalten gemacht.
Coroutinen sind spezielle Funktionen, die ihre Ausführung anhalten und die Kontrolle an andere Coroutinen übergeben können. Sie werden mit dem Schlüsselwort „async“ definiert und können mit dem Schlüsselwort „await“ abgewartet werden. Hier ist ein einfaches Beispiel:
async def greet(name): print(f"Hello, {name}!") await asyncio.sleep(1) print(f"Goodbye, {name}!") async def main(): await greet("Alice") await greet("Bob") asyncio.run(main())
In diesem Code ist die Begrüßungsfunktion eine Coroutine, die eine Begrüßung ausgibt, eine Sekunde wartet und sich dann verabschiedet. Die Hauptfunktion ruft zweimal auf und wir verwenden asyncio.run, um die Haupt-Coroutine auszuführen.
Aber was macht Coroutinen so besonders? Sie ermöglichen es uns, gleichzeitigen Code zu schreiben, der wie synchroner Code aussieht und sich verhält, aber tatsächlich mehrere Vorgänge gleichzeitig ausführen kann. Dies ist besonders nützlich für E/A-gebundene Aufgaben wie Netzwerkoperationen oder Dateiverwaltung.
Lassen Sie uns tiefer in die Asyncio-Bibliothek eintauchen, die die Grundlage für die asynchrone Programmierung in Python bildet. Im Mittelpunkt steht die Ereignisschleife, die die Ausführung von Coroutinen verwaltet. Sie können es sich als einen Planer vorstellen, der entscheidet, welche Coroutine als nächstes ausgeführt wird.
So können wir Aufgaben mit Asyncio erstellen und verwenden:
import asyncio async def fetch_data(url): print(f"Fetching data from {url}") await asyncio.sleep(2) # Simulating network delay return f"Data from {url}" async def main(): urls = ['http://example.com', 'http://example.org', 'http://example.net'] tasks = [asyncio.create_task(fetch_data(url)) for url in urls] results = await asyncio.gather(*tasks) for result in results: print(result) asyncio.run(main())
In diesem Beispiel simulieren wir das gleichzeitige Abrufen von Daten von mehreren URLs. Die Funktion asyncio.create_task verwandelt unsere Coroutinen in Aufgaben, die dann gleichzeitig mit asyncio.gather ausgeführt werden.
Lassen Sie uns nun über strukturierte Parallelität sprechen. Dies ist ein Paradigma, das darauf abzielt, gleichzeitigen Code vorhersehbarer und leichter nachvollziehbar zu machen. Mit Python 3.11 wurden einige neue Funktionen zur Unterstützung strukturierter Parallelität eingeführt, z. B. Aufgabengruppen.
So können wir eine Aufgabengruppe verwenden:
import asyncio async def process_item(item): await asyncio.sleep(1) return f"Processed {item}" async def main(): async with asyncio.TaskGroup() as tg: task1 = tg.create_task(process_item("A")) task2 = tg.create_task(process_item("B")) task3 = tg.create_task(process_item("C")) print(task1.result()) print(task2.result()) print(task3.result()) asyncio.run(main())
Die TaskGroup stellt sicher, dass alle Aufgaben abgeschlossen (oder abgebrochen) sind, bevor wir fortfahren. Dies trägt dazu bei, Probleme wie vergessene Aufgaben oder unerwartete Interaktionen zwischen gleichzeitigen Vorgängen zu vermeiden.
Einer der mächtigsten Aspekte von Coroutinen ist ihre Fähigkeit, I/O-Vorgänge effizient abzuwickeln. Schauen wir uns ein Beispiel eines einfachen asynchronen Webservers an:
import asyncio from aiohttp import web async def handle(request): name = request.match_info.get('name', "Anonymous") text = f"Hello, {name}!" return web.Response(text=text) async def main(): app = web.Application() app.add_routes([web.get('/', handle), web.get('/{name}', handle)]) runner = web.AppRunner(app) await runner.setup() site = web.TCPSite(runner, 'localhost', 8080) await site.start() print("Server started at http://localhost:8080") await asyncio.Event().wait() asyncio.run(main())
Dieser Server kann dank der Leistungsfähigkeit von Coroutinen mehrere Verbindungen gleichzeitig verarbeiten. Jede Anfrage wird in einer eigenen Coroutine verarbeitet, sodass der Server auch unter hoher Last reaktionsfähig bleibt.
Lassen Sie uns einige fortgeschrittenere Konzepte erkunden. Die Stornierung ist eine wichtige Funktion bei gleichzeitigen Vorgängen. Manchmal müssen wir eine Aufgabe stoppen, bevor sie abgeschlossen ist. So können wir das machen:
async def greet(name): print(f"Hello, {name}!") await asyncio.sleep(1) print(f"Goodbye, {name}!") async def main(): await greet("Alice") await greet("Bob") asyncio.run(main())
In diesem Beispiel erstellen wir eine Aufgabe mit langer Laufzeit und brechen sie nach 5 Sekunden ab. Die Aufgabe fängt den CancelledError ab und führt alle erforderlichen Bereinigungen durch, bevor sie beendet wird.
Eine weitere leistungsstarke Funktion ist die Möglichkeit, benutzerdefinierte Ereignisschleifen zu erstellen. Während die Standard-Ereignisschleife für die meisten Fälle ausreicht, benötigen wir manchmal mehr Kontrolle. Hier ist ein einfaches Beispiel einer benutzerdefinierten Ereignisschleife:
import asyncio async def fetch_data(url): print(f"Fetching data from {url}") await asyncio.sleep(2) # Simulating network delay return f"Data from {url}" async def main(): urls = ['http://example.com', 'http://example.org', 'http://example.net'] tasks = [asyncio.create_task(fetch_data(url)) for url in urls] results = await asyncio.gather(*tasks) for result in results: print(result) asyncio.run(main())
Dies ist eine sehr einfache benutzerdefinierte Ereignisschleife, die jedoch das Prinzip demonstriert. Sie können dies erweitern, um Funktionen wie eine bessere Planung, Überwachung oder Integration mit anderen Systemen hinzuzufügen.
Lassen Sie uns über einige Best Practices bei der Arbeit mit Coroutinen und strukturierter Parallelität sprechen. Verwenden Sie zunächst immer „async with“, um asynchrone Kontextmanager zu verwalten. Dies gewährleistet einen ordnungsgemäßen Auf- und Abbau, auch wenn Ausnahmen auftreten:
import asyncio async def process_item(item): await asyncio.sleep(1) return f"Processed {item}" async def main(): async with asyncio.TaskGroup() as tg: task1 = tg.create_task(process_item("A")) task2 = tg.create_task(process_item("B")) task3 = tg.create_task(process_item("C")) print(task1.result()) print(task2.result()) print(task3.result()) asyncio.run(main())
Zweitens: Seien Sie vorsichtig bei Blockierungsvorgängen. Wenn Sie eine CPU-gebundene Aufgabe ausführen müssen, sollten Sie asyncio.to_thread verwenden, um sie in einem separaten Thread auszuführen:
import asyncio from aiohttp import web async def handle(request): name = request.match_info.get('name', "Anonymous") text = f"Hello, {name}!" return web.Response(text=text) async def main(): app = web.Application() app.add_routes([web.get('/', handle), web.get('/{name}', handle)]) runner = web.AppRunner(app) await runner.setup() site = web.TCPSite(runner, 'localhost', 8080) await site.start() print("Server started at http://localhost:8080") await asyncio.Event().wait() asyncio.run(main())
Drittens verwenden Sie asyncio.wait, wenn Sie mehr Kontrolle über eine Gruppe von Aufgaben benötigen. Sie können damit warten, bis die erste Aufgabe abgeschlossen ist, oder eine Zeitüberschreitung festlegen:
import asyncio async def long_running_task(): try: while True: print("Working...") await asyncio.sleep(1) except asyncio.CancelledError: print("Task was cancelled") async def main(): task = asyncio.create_task(long_running_task()) await asyncio.sleep(5) task.cancel() try: await task except asyncio.CancelledError: print("Main: task was cancelled") asyncio.run(main())
Das Debuggen von gleichzeitigem Code kann eine Herausforderung sein. Pythons Asyncio enthält einige hilfreiche Tools. Sie können den Debug-Modus aktivieren, um eine detailliertere Protokollierung zu erhalten:
import asyncio class MyEventLoop(asyncio.BaseEventLoop): def __init__(self): self._running = False self._ready = asyncio.Queue() def run_forever(self): self._running = True while self._running: coro = self._ready.get_nowait() if coro: coro.send(None) def stop(self): self._running = False def call_soon(self, callback, *args): self._ready.put_nowait(callback(*args)) # Usage loop = MyEventLoop() asyncio.set_event_loop(loop) async def my_coroutine(): print("Hello from my coroutine!") loop.call_soon(my_coroutine) loop.run_forever()
Sie können auch die aiodebug-Bibliothek für erweiterte Debugging-Funktionen verwenden.
Sehen wir uns ein komplexeres Beispiel an: eine parallele Datenverarbeitungspipeline. Dies könnte für Aufgaben wie die Verarbeitung großer Datensätze oder den Umgang mit Streaming-Daten nützlich sein:
async with aiohttp.ClientSession() as session: async with session.get('http://example.com') as response: html = await response.text()
Diese Pipeline zeigt, wie wir Warteschlangen verwenden können, um Daten zwischen verschiedenen Verarbeitungsstufen zu übergeben, die alle gleichzeitig laufen.
Coroutinen und strukturierte Parallelität haben neue Möglichkeiten in der Python-Programmierung eröffnet. Sie ermöglichen es uns, effizienten, gleichzeitigen Code zu schreiben, der einfacher zu überdenken und zu warten ist. Unabhängig davon, ob Sie Webserver, Datenverarbeitungspipelines oder reaktionsfähige GUIs erstellen, können diese Tools Ihnen bei der Erstellung robuster, leistungsstarker Anwendungen helfen.
Denken Sie daran: Der Schlüssel zur Beherrschung dieser Konzepte ist Übung. Beginnen Sie mit einfachen Beispielen und steigern Sie sich schrittweise zu komplexeren Anwendungsfällen. Achten Sie auf Fehlerbehandlung und -beseitigung, da diese für den Aufbau zuverlässiger asynchroner Systeme von entscheidender Bedeutung sind. Und scheuen Sie sich nicht, in den Asyncio-Quellcode einzutauchen – es ist eine großartige Möglichkeit, Ihr Verständnis dafür zu vertiefen, wie diese leistungsstarken Funktionen unter der Haube funktionieren.
Während Sie sich weiterhin mit Coroutinen und strukturierter Parallelität beschäftigen, werden Sie neue Muster und Techniken entdecken, die Ihren Code effizienter und ausdrucksvoller machen können. Es ist ein spannender Bereich der Python-Entwicklung, der sich ständig weiterentwickelt. Lernen Sie also weiter, experimentieren Sie weiter und genießen Sie die Reise in die Welt der asynchronen Programmierung!
Schauen Sie sich unbedingt unsere Kreationen an:
Investor Central | Intelligentes Leben | Epochen & Echos | Rätselhafte Geheimnisse | Hindutva | Elite-Entwickler | JS-Schulen
Tech Koala Insights | Epochs & Echoes World | Investor Central Medium | Puzzling Mysteries Medium | Wissenschaft & Epochen Medium | Modernes Hindutva
Das obige ist der detaillierte Inhalt vonBeherrschen Sie die Coroutinen von Python: Steigern Sie die Effizienz und Leistung Ihres Codes. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!