Beherrschen Sie die Coroutinen von Python: Steigern Sie die Effizienz und Leistung Ihres Codes

Mary-Kate Olsen
Freigeben: 2024-11-23 09:21:22
Original
832 Leute haben es durchsucht

Mastering Python

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())
Nach dem Login kopieren
Nach dem Login kopieren

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())
Nach dem Login kopieren
Nach dem Login kopieren

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())
Nach dem Login kopieren
Nach dem Login kopieren

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())
Nach dem Login kopieren
Nach dem Login kopieren

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())
Nach dem Login kopieren
Nach dem Login kopieren

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())
Nach dem Login kopieren
Nach dem Login kopieren

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())
Nach dem Login kopieren
Nach dem Login kopieren

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())
Nach dem Login kopieren
Nach dem Login kopieren

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())
Nach dem Login kopieren

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()
Nach dem Login kopieren

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()
Nach dem Login kopieren

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!


Unsere Kreationen

Schauen Sie sich unbedingt unsere Kreationen an:

Investor Central | Intelligentes Leben | Epochen & Echos | Rätselhafte Geheimnisse | Hindutva | Elite-Entwickler | JS-Schulen


Wir sind auf Medium

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!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage