Asynchrone Programmierung mit Asyncio

PHPz
Freigeben: 2024-07-23 16:59:24
Original
690 Leute haben es durchsucht

Asynchronous Programming with Asyncio

In der Programmierwelt ist das Konzept der „Nicht-Blockierung“ allgegenwärtig. JavaScript-Entwickler verwenden häufig den Begriff „asynchron“, da er eine der Stärken von JavaScript darstellt. Um die asynchrone Programmierung wirklich zu verstehen, ist es jedoch wichtig, die Konzepte der gleichzeitigen und parallelen Programmierung zu verstehen.

Gleichzeitige Programmierung

Wenn mehrere unabhängige Einheiten gleichzeitig arbeiten, erfolgt die Programmierung gleichzeitig. Dies bedeutet nicht unbedingt, dass diese Aufgaben genau gleichzeitig ausgeführt werden. Stattdessen bedeutet dies, dass Aufgaben im Laufe der Zeit Fortschritte machen, indem sie Ressourcen, wie z. B. CPU-Zeit, gemeinsam nutzen. Der Hauptvorteil der gleichzeitigen Programmierung ist ihre Robustheit: Wenn ein Prozess abstürzt, funktioniert der Rest Ihres Programms weiterhin.

Parallele Programmierung

Wenn ein Algorithmus seine Arbeit in mehrere Teile aufteilen kann, ist er parallel. Je mehr Prozessoren Sie haben, desto mehr profitieren Sie von der Parallelität. Effiziente Parallelprogrammierung optimiert die Ressourcen moderner Maschinen für eine bessere Leistung.

Veranschaulichung von Parallelität vs. Parallelität beim Kochen

Beispiel für Parallelität:

Stellen Sie sich vor, Sie bereiten eine Mahlzeit zu, bei der Sie etwas Fleisch grillen und eine Soße zubereiten müssen. Sie beginnen damit, das Fleisch auf den Grill zu legen. Während das Fleisch grillt, hacken Sie die Tomaten und anderes Gemüse für die Soße. Dann fangen Sie an, die Soße zu kochen, während Sie gelegentlich das Fleisch kontrollieren. Hier sind beide Aufgaben (Fleisch grillen und Soße zubereiten) im Gange, aber Sie wechseln Ihre Aufmerksamkeit zwischen ihnen. Dies stellt Parallelität dar.

Parallelitätsbeispiel:

Angenommen, Sie haben einen Freund, der Ihnen hilft. Während Sie sich auf das Grillen des Fleisches konzentrieren, kümmert sich Ihr Freund um die Zubereitung der Soße. Beide Aufgaben werden gleichzeitig erledigt, ohne dass die Aufmerksamkeit zwischen ihnen gewechselt werden muss. Dies stellt Parallelität dar.

Was ist asynchrone Programmierung?

Asynchrone Programmierung umfasst die Verarbeitung von Eingabe-/Ausgabevorgängen (E/A), die außerhalb Ihres Programms stattfinden, wie z. B. Benutzereingaben, Drucken auf einem Terminal, Lesen von einem Socket oder Schreiben auf die Festplatte. Die Hauptmerkmale asynchroner E/A sind:

  • Die für den Vorgang benötigte Zeit ist nicht CPU-abhängig. Stattdessen hängt es von Faktoren wie Festplattengeschwindigkeit, Netzwerklatenz und anderen externen Bedingungen ab.

  • Das Programm kann nicht vorhersagen, wann der Vorgang enden wird.

Bei Diensten mit erheblichen E/A-Vorgängen (wie Webservern, Datenbanken und Bereitstellungsskripts) kann die Optimierung dieser Vorgänge die Leistung erheblich verbessern.

Sehen wir uns Beispiele für blockierenden Code und nicht blockierenden Code an.

Beispiel für blockierenden und nicht blockierenden Code

Stellen Sie sich ein einfaches Programm vor:

import time

def task():
    time.sleep(2)
    print("Hello")

for _ in range(3):
    task()
Nach dem Login kopieren
Nach dem Login kopieren

In diesem synchronen Programm wartet jede Aufgabe auf den Abschluss der vorherigen, was zu Verzögerungen führt.

Sehen wir uns nun eine asynchrone Version mit asyncio an:

import asyncio

async def task():
    await asyncio.sleep(2)
    print("Hello")

async def main():
    tasks = [task() for _ in range(3)]
    await asyncio.gather(*tasks)

asyncio.run(main())
Nach dem Login kopieren
Nach dem Login kopieren

In diesem asynchronen Programm werden Aufgaben gleichzeitig ausgeführt, wodurch die Gesamtausführungszeit verkürzt wird. Lassen Sie uns die Komponenten der asynchronen Programmierung erkunden.

Komponenten der asynchronen Programmierung

Ereignisschleifen, Coroutinen und Futures sind die wesentlichen Elemente eines asynchronen Python-Programms.

  • Ereignisschleife: Verwaltet den Aufgabenwechsel und den Ausführungsfluss und verfolgt die Aufgaben, die asynchron ausgeführt werden sollen.

  • Coroutinen: Spezielle Funktionen, die angehalten und fortgesetzt werden können, sodass während der Wartezeit andere Aufgaben ausgeführt werden können. Eine Coroutine gibt an, wo in der Funktion das Taskwechselereignis stattfinden soll, und gibt die Kontrolle an die Ereignisschleife zurück. Coroutinen werden normalerweise von der Ereignisschleife erstellt und intern in einer Aufgabenwarteschlange gespeichert.

  • Futures: Platzhalter für Ergebnisse von Coroutinen, die das Ergebnis oder Ausnahmen speichern. Sobald die Ereignisschleife eine Coroutine initiiert, wird eine entsprechende Zukunft erstellt, die das Ergebnis der Coroutine oder eine Ausnahme speichert, falls während der Ausführung der Coroutine eine ausgelöst wurde.

Nachdem wir die entscheidenden Teile der asynchronen Programmierung in Python erklärt haben, schreiben wir etwas Code.

Asynchronen Code schreiben

Da Sie nun das asynchrone Programmiermuster verstanden haben, schreiben wir ein kleines Skript und analysieren die Ausführung. Hier ist ein einfaches asynchrones Skript:

import asyncio

async def task():
    await asyncio.sleep(2)
    print("Hello")

async def main():
    tasks = [task() for _ in range(3)]
    await asyncio.gather(*tasks)

asyncio.run(main())
Nach dem Login kopieren
Nach dem Login kopieren

Im obigen Code versuchen wir, die Ausführung anderer Aufgaben fortzusetzen, auch wenn eine andere Ausführung schläft (blockiert). Beachten Sie das Schlüsselwort async vor der Aufgabe und den Hauptfunktionen.

Diese Funktionen sind jetzt Coroutinen.

Coroutines functions in Python are preceded by the keyword async. The main() function here is the task coordinator or our single event loop, as it executes all tasks using the async.gather method. The asyncio.gather function runs awaitable objects concurrently.

Output:

Hello
Hello
Hello
Program executed in 2.01 seconds.
Nach dem Login kopieren

When each task reaches await asyncio.sleep(2), it simply goes to the next task and comes back when it's finished. It's like saying, "I am going to sleep for 2 seconds. Do something else."

Let's see the synchronous version for a quick comparison.

import time

def task():
    time.sleep(2)
    print("Hello")

for _ in range(3):
    task()
Nach dem Login kopieren
Nach dem Login kopieren

In the code above, we are going the traditional programming way in Python. You will notice that the execution of the process will take much more time.

Output:

Hello
Hello
Hello
Program executed in 6.01 seconds.
Nach dem Login kopieren

Now you can notice the execution time. Think of time.sleep() as a blocking task and asyncio.sleep() as a non-blocking or long task. In asynchronous programming, the benefit of awaiting something, like asyncio.sleep(), is that the surrounding function can temporarily cede control to another function that is ready to execute immediately.

With some basic examples of asynchronous programming in Python understood, let's explore the rules of asynchronous programming in Python.

Rules of Asyncio Programming

  1. Coroutines: Coroutines cannot be executed directly. If you try to run a coroutine function directly, it returns a coroutine object. Instead, use asyncio.run():

    import asyncio
    
    async def hello():
        await asyncio.sleep(1)
        print('Hello')
    
    asyncio.run(hello())
    
    Nach dem Login kopieren
  2. Awaitable Objects: Coroutines, futures, and tasks are the main awaitable objects. Python coroutines are awaitables and can be awaited from other coroutines.

  3. Await Keyword:await can only be used within async functions.

    async def hello():
        await asyncio.sleep(1)
        print("Hello")
    
    Nach dem Login kopieren
  4. Compatibility: Not all Python modules are compatible with asynchronous programming. For example, replacing await asyncio.sleep() with time.sleep() will cause an error. You can check the list of compatible and maintained modules here.

In the next section, we will explore a common use of asynchronous programming, HTTP requests.

Program Example: Asynchronous Requests

Let's take a look at the following piece of code:

import aiohttp
import asyncio

async def fetch(session, city):
    url = f"https://www.prevision-meteo.ch/services/json/{city}"
    async with session.get(url) as response:
        data = await response.json()
        print(f"Temperature at {city}: {data['current_condition']['tmp']} C")

async def main():
    async with aiohttp.ClientSession() as session:
        cities = ['paris', 'toulouse', 'marseille']
        tasks = [fetch(session, city) for city in cities]
        await asyncio.gather(*tasks)

asyncio.run(main())
Nach dem Login kopieren

In the code above, we create two asynchronous functions: one to fetch data from the prevision-meteo URL and a main function to execute the processes in the Python code. The goal is to send asynchronous HTTP GET requests to retrieve temperatures and print the responses.

In the main and fetch functions, we use async with. In the fetch function, async with ensures that the connection is closed properly. In the main function, it ensures that the ClientSession is closed after completing the requests. These practices are important in asynchronous coding in Python to manage resources efficiently and prevent leaks.

In the last line of the main function, we use await asyncio.gather(*tasks). In our case, it runs all tasks concurrently, allowing the program to send multiple HTTP requests simultaneously. Using await ensures that the program waits for all tasks to complete before proceeding.

Output:

Temperature at marseille: 25 C
Temperature at toulouse: 24 C
Temperature at paris: 18 C
Program executed in 5.86 seconds.
Nach dem Login kopieren

Synchronous Version for Comparison

Code:

import requests
import time

def fetch(city):
    url = f"https://www.prevision-meteo.ch/services/json/{city}"
    response = requests.get(url)
    data = response.json()
    print(f"Temperature at {city}: {data['current_condition']['tmp']} C")

def main():
    cities = ['paris', 'toulouse', 'marseille']
    for city in cities:
        fetch(city)

start_time = time.time()
main()
print(f"Program executed in {time.time() - start_time:.2f} seconds.")
Nach dem Login kopieren

Output:

Temperature at Paris: 18 C
Temperature at Toulouse: 24 C
Temperature at Marseille: 25 C
Program executed in 9.01 seconds.
Nach dem Login kopieren

When to Use Asynchronous Programming

The asynchronous model performs best when:

  • There are a large number of tasks, ensuring at least one task can always progress.

  • Tasks involve significant I/O, causing an asynchronous program to waste lots of time blocking when other tasks could be running.

  • Tasks are largely independent, minimizing inter-task communication (and thus for one task to wait upon another).

Conclusion

In this tutorial, we covered:

  • The concepts of asynchronous programming and related concepts.

  • Effective use of async/await.

  • Making asynchronous HTTP requests with aiohttp.

  • The benefits of asynchronous programming.

Thanks for reading. The second part will cover asynchronous programming with Django.

Resources

  • Python Documentation: Coroutines and Tasks

  • Python Documentation: asyncio - Asynchronous I/O

  • aiohttp Documentation

  • Aio Libraries

  • Concurrency vs Parallelism

Das obige ist der detaillierte Inhalt vonAsynchrone Programmierung mit Asyncio. 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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage