Weiter zum Inhalt

Asyncio: Eine Einführung

Eine kurze Einführung in asynchrones I/O mit dem asyncio-Paket.
Aktualisiert 18. Sept. 2026  · 12 Min. lesen

Mit KI erkunden

ChatGPTClaudePerplexity

Das Modul asyncio wurde in Python 3.4 zunächst als vorläufiges Paket hinzugefügt. Das bedeutet, dass asyncio rückwärtsinkompatible Änderungen erhalten oder in einer zukünftigen Python-Version sogar entfernt werden könnte.

Laut Dokumentation „bietet asyncio die Infrastruktur, um nebenläufigen Single-Thread-Code mit Coroutinen zu schreiben, I/O-Zugriffe über Sockets und andere Ressourcen zu multiplexen, Netzwerk-Clients und -Server auszuführen und weitere verwandte Primitive bereitzustellen“. Dieses Kapitel will nicht alles abdecken, was mit asyncio möglich ist, aber du lernst, wie das Modul funktioniert und warum es nützlich ist.

Wenn du etwas wie asyncio für eine ältere Python-Version brauchst, wirf einen Blick auf Twisted oder gevent.

Begriffe

Das asyncio-Modul stellt ein Framework bereit, dessen Kern der Event-Loop ist. Ein Event-Loop wartet im Grunde darauf, dass etwas passiert, und reagiert dann auf das Ereignis. Er ist zuständig für Dinge wie I/O- und Systemereignisse.

asyncio bringt tatsächlich mehrere Loop-Implementierungen mit. Standardmäßig wählt das Modul die für das jeweilige Betriebssystem voraussichtlich effizienteste aus; du kannst den Event-Loop aber auch explizit festlegen. Ein Event-Loop folgt dem Prinzip: „Wenn Ereignis A eintritt, reagiere mit Funktion B“.

Denk an einen Server, der darauf wartet, dass jemand eine Ressource anfragt, zum Beispiel eine Webseite. Ist die Seite nicht sehr populär, ist der Server lange untätig. Kommt eine Anfrage, muss er reagieren. Diese Reaktion nennt man Event-Handling. Wenn ein User die Seite lädt, prüft der Server einen oder mehrere Event-Handler und ruft sie auf. Sobald diese fertig sind, geben sie die Kontrolle an den Event-Loop zurück. In Python nutzt asyncio dafür Coroutinen.

Eine Coroutine ist eine spezielle Funktion, die die Kontrolle an ihren Aufrufer abgeben kann, ohne ihren Zustand zu verlieren. Sie ist ein Verbraucher und eine Weiterentwicklung eines Generators. Ein großer Vorteil gegenüber Threads: Sie benötigen sehr wenig Speicher. Beachte: Wenn du eine Coroutine-Funktion aufrufst, wird sie nicht sofort ausgeführt. Stattdessen gibt sie ein Coroutine-Objekt zurück, das du dem Event-Loop übergeben kannst – zur sofortigen oder späteren Ausführung.

Ein weiterer Begriff, dem du bei asyncio begegnest, ist Future. Eine Future ist ein Objekt, das das Ergebnis einer noch nicht abgeschlossenen Arbeit repräsentiert. Dein Event-Loop kann Futures beobachten und auf deren Abschluss warten. Wenn eine Future fertig ist, steht sie auf done. Asyncio unterstützt außerdem Locks und Semaphore.

Zuletzt noch die Task. Eine Task ist ein Wrapper um eine Coroutine und eine Unterklasse von Future. Tasks lassen sich auch über den Event-Loop planen.

async und await

Die Schlüsselwörter async und await kamen mit Python 3.5 hinzu, um native Coroutinen zu definieren und sie klar von generatorbasierten Coroutinen abzugrenzen. Für eine detaillierte Beschreibung von async und await lies PEP 492.

In Python 3.4 würdest du eine Coroutine so erstellen:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgUHl0aG9uIDMuNCBjb3JvdXRpbmUgZXhhbXBsZVxuIyBJbXBvcnQgYGFzeW5jaW9gXG5pbXBvcnQgX19fX19fX1xuIFxuQGFzeW5jaW8uY29yb3V0aW5lXG5kZWYgbXlfY29ybygpOlxuICAgIHlpZWxkIGZyb20gZnVuYygpIiwic29sdXRpb24iOiIjIFB5dGhvbiAzLjQgY29yb3V0aW5lIGV4YW1wbGVcbmltcG9ydCBhc3luY2lvXG4gXG5AYXN5bmNpby5jb3JvdXRpbmVcbmRlZiBteV9jb3JvKCk6XG4gICAgeWllbGQgZnJvbSBmdW5jKCkiLCJzY3QiOiJFeCgpLnRlc3RfaW1wb3J0KFwiYXN5bmNpb1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJAYXN5bmNpby5jb3JvdXRpbmVcIiwgcGF0dGVybj1GYWxzZSxub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBhZGQgYEBhc3luY2lvLmNvcm91dGluZWAgdG8gdGhlIGNvZGU/XCIpXG5FeCgpLnRlc3RfZnVuY3Rpb25fZGVmaW5pdGlvbihcIm15X2Nvcm9cIilcbnN1Y2Nlc3NfbXNnKFwiWW91IGhhdmUgc3VjY2Vzc2Z1bGx5IGNyZWF0ZWQgYSBjb3JvdXRpbmUgaW4gUHl0aG9uIDMuNCEgQnV0IHdoYXQgYWJvdXQgbWFraW5nIHRoaXMgY29yb3V0aW5lIGluIFB5dGhvbiAzLjU/XCIpIn0=

Dieser Decorator funktioniert auch in Python 3.5 noch, aber das types-Modul hat eine Erweiterung in Form einer coroutine function erhalten, die dir nun sagen kann, ob es sich um eine native Coroutine handelt oder nicht. Ab Python 3.5 kannst du mit async def eine Coroutine-Funktion auch syntaktisch definieren.

Die Funktion von oben sähe dann so aus:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImltcG9ydCBfX19fX19fXG4gXG5hc3luYyBkZWYgX19fX19fXygpOlxuICAgIGF3YWl0IGZ1bmMoKSIsInNvbHV0aW9uIjoiaW1wb3J0IGFzeW5jaW9cbiBcbmFzeW5jIGRlZiBteV9jb3JvKCk6XG4gICAgYXdhaXQgZnVuYygpIiwic2N0IjoiRXgoKS50ZXN0X2ltcG9ydChcImFzeW5jaW9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwiYXN5bmMgZGVmIG15X2Nvcm8oKTpcIiwgcGF0dGVybj1GYWxzZSwgbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgZGVmaW5lIHRoZSBhc3luYyBkZWYgZnVuY3Rpb24gYG15X2Nvcm8oKWA/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcImF3YWl0IGZ1bmMoKVwiLCBwYXR0ZXJuPUZhbHNlLCBub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBhZGQgYGF3YWl0IGZ1bmN0KClgIHRvIHRoZSBhc3luYyBkZWYgZnVuY3Rpb24gYG15X2Nvcm8oKWA/XCIpXG5zdWNjZXNzX21zZyhcIldlbGwgZG9uZSEgWW91IGhhdmUgbm93IGNyZWF0ZWQgYSBjb3JvdXRpbmUgdXNpbmcgUHl0aG9uIDMuNSFcIikifQ==

Wenn du eine Coroutine auf diese Weise definierst, kannst du innerhalb der Funktion kein yield verwenden. Stattdessen muss sie eine return- oder await-Anweisung enthalten, um Werte an den Aufrufer zurückzugeben. Beachte: Das Schlüsselwort await darf nur in einer async def-Funktion verwendet werden.

Die Schlüsselwörter async/await kannst du als API für asynchrones Programmieren betrachten. Das asyncio-Modul ist „nur“ ein Framework, das async/await für asynchrone Programmierung nutzt. Es gibt sogar ein Projekt namens curio, das dieses Konzept belegt – eine separate Event-Loop-Implementierung, die unter der Haube async/await verwendet.

Ein schlechtes Coroutine-Beispiel

Hintergrundwissen ist hilfreich, aber manchmal willst du einfach Beispiele sehen, um ein Gefühl für die Syntax und das Zusammenspiel der Teile zu bekommen.

Fangen wir also mit einem einfachen Beispiel an!

Eine ziemlich typische Aufgabe ist das Herunterladen einer Datei – sei es aus einer internen Quelle oder aus dem Internet. Meistens willst du gleich mehrere Dateien herunterladen.

Lass uns dafür zwei Coroutinen schreiben:

import asyncio
import os
import urllib.request
 
async def download_coroutine(url):
    #"A coroutine to download the specified url"
    request = urllib.request.urlopen(url)
    filename = os.path.basename(url)
 
    with open(filename, 'wb') as file_handle:
        while True:
            chunk = request.read(1024)
            if not chunk:
                break
            file_handle.write(chunk)
    msg = 'Finished downloading {filename}'.format(filename=filename)
    return msg
 
async def main(urls):
    """
    Creates a group of coroutines and waits for them to finish
    """
    coroutines = [download_coroutine(url) for url in urls]
    completed, pending = await asyncio.wait(coroutines)
    for item in completed:
        print(item.result())
 
 
if __name__ == '__main__':
    urls = ["http://www.irs.gov/pub/irs-pdf/f1040.pdf",
            "http://www.irs.gov/pub/irs-pdf/f1040a.pdf",
            "http://www.irs.gov/pub/irs-pdf/f1040ez.pdf",
            "http://www.irs.gov/pub/irs-pdf/f1040es.pdf",
            "http://www.irs.gov/pub/irs-pdf/f1040sb.pdf"]
 
    event_loop = asyncio.get_event_loop()
    try:
        event_loop.run_until_complete(main(urls))
    finally:
        event_loop.close()

Hier importieren wir die benötigten Module und erstellen mit der async-Syntax unsere erste Coroutine. Diese Coroutine heißt download_coroutine und nutzt Pythons urllib, um die übergebene URL herunterzuladen. Ist sie fertig, gibt sie eine entsprechende Meldung zurück.

Die andere Coroutine ist unsere Main-Coroutine. Sie nimmt eine Liste aus einer oder mehreren URLs, reiht sie in die Warteschlange ein und wartet mit asyncio.wait auf deren Abschluss. Damit die Coroutinen überhaupt starten, müssen sie dem Event-Loop hinzugefügt werden. Das geschieht am Ende: Wir holen uns den Event-Loop und rufen seine Methode run_until_complete auf. Der Event-Loop erhält die Main-Coroutine, welche die zweite Coroutine einreiht und startet. Das nennt man eine verkettete Coroutine.

Das Problem an diesem Beispiel: Eigentlich ist es gar nicht asynchron. Der Grund ist, dass die Funktion download_coroutine nicht asynchron arbeitet. urllib ist nicht asynchron, und außerdem verwenden wir weder await noch yield. Besser wäre hier das Paket aiohttp. Schauen wir uns das als Nächstes an!

Ein besseres Coroutine-Beispiel

Das Paket aiohttp ist für die Erstellung asynchroner HTTP-Clients und -Server gedacht. Du kannst es mit pip so installieren:

pip install aiohttp

Nachdem es installiert ist, passen wir unseren Code an aiohttp an, um die Dateien herunterzuladen:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImltcG9ydCBhaW9odHRwXG5pbXBvcnQgYXN5bmNpb1xuaW1wb3J0IGFzeW5jX3RpbWVvdXRcbmltcG9ydCBvc1xuIFxuYXN5bmMgZGVmIGRvd25sb2FkX2Nvcm91dGluZShzZXNzaW9uLCB1cmwpOlxuICAgIHdpdGggYXN5bmNfdGltZW91dC50aW1lb3V0KDEwKTpcbiAgICAgICAgYXN5bmMgd2l0aCBzZXNzaW9uLmdldCh1cmwpIGFzIHJlc3BvbnNlOlxuICAgICAgICAgICAgZmlsZW5hbWUgPSBfXy5wYXRoLmJhc2VuYW1lKHVybClcbiAgICAgICAgICAgIHdpdGggb3BlbihfX19fX19fXywgJ3diJykgYXMgZl9oYW5kbGU6XG4gICAgICAgICAgICAgICAgd2hpbGUgVHJ1ZTpcbiAgICAgICAgICAgICAgICAgICAgY2h1bmsgPSBhd2FpdCByZXNwb25zZS5jb250ZW50LnJlYWQoMTAyNClcbiAgICAgICAgICAgICAgICAgICAgaWYgbm90IGNodW5rOlxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgICAgICAgZl9oYW5kbGUud3JpdGUoX19fX18pXG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgcmVzcG9uc2UucmVsZWFzZSgpXG4gXG5hc3luYyBkZWYgbWFpbihsb29wKTpcbiAgICB1cmxzID0gW1wiaHR0cDovL3d3dy5pcnMuZ292L3B1Yi9pcnMtcGRmL2YxMDQwLnBkZlwiLFxuICAgICAgICBcImh0dHA6Ly93d3cuaXJzLmdvdi9wdWIvaXJzLXBkZi9mMTA0MGEucGRmXCIsXG4gICAgICAgIFwiaHR0cDovL3d3dy5pcnMuZ292L3B1Yi9pcnMtcGRmL2YxMDQwZXoucGRmXCIsXG4gICAgICAgIFwiaHR0cDovL3d3dy5pcnMuZ292L3B1Yi9pcnMtcGRmL2YxMDQwZXMucGRmXCIsXG4gICAgICAgIFwiaHR0cDovL3d3dy5pcnMuZ292L3B1Yi9pcnMtcGRmL2YxMDQwc2IucGRmXCJdXG4gXG4gICAgYXN5bmMgd2l0aCBhaW9odHRwLkNsaWVudFNlc3Npb24obG9vcD1sb29wKSBhcyBzZXNzaW9uOlxuICAgICAgICB0YXNrcyA9IFtkb3dubG9hZF9jb3JvdXRpbmUoc2Vzc2lvbiwgdXJsKSBmb3IgdXJsIGluIHVybHNdXG4gICAgICAgIGF3YWl0IGFzeW5jaW8uZ2F0aGVyKCp0YXNrcylcbiBcbmlmIF9fbmFtZV9fID09ICdfX21haW5fXyc6XG4gICAgbG9vcCA9IGFzeW5jaW8uZ2V0X2V2ZW50X2xvb3AoKVxuICAgIGxvb3AucnVuX3VudGlsX2NvbXBsZXRlKG1haW4obG9vcCkpIiwic29sdXRpb24iOiJpbXBvcnQgYWlvaHR0cFxuaW1wb3J0IGFzeW5jaW9cbmltcG9ydCBhc3luY190aW1lb3V0XG5pbXBvcnQgb3NcbiBcbmFzeW5jIGRlZiBkb3dubG9hZF9jb3JvdXRpbmUoc2Vzc2lvbiwgdXJsKTpcbiAgICB3aXRoIGFzeW5jX3RpbWVvdXQudGltZW91dCgxMCk6XG4gICAgICAgIGFzeW5jIHdpdGggc2Vzc2lvbi5nZXQodXJsKSBhcyByZXNwb25zZTpcbiAgICAgICAgICAgIGZpbGVuYW1lID0gb3MucGF0aC5iYXNlbmFtZSh1cmwpXG4gICAgICAgICAgICB3aXRoIG9wZW4oZmlsZW5hbWUsICd3YicpIGFzIGZfaGFuZGxlOlxuICAgICAgICAgICAgICAgIHdoaWxlIFRydWU6XG4gICAgICAgICAgICAgICAgICAgIGNodW5rID0gYXdhaXQgcmVzcG9uc2UuY29udGVudC5yZWFkKDEwMjQpXG4gICAgICAgICAgICAgICAgICAgIGlmIG5vdCBjaHVuazpcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgICAgICAgIGZfaGFuZGxlLndyaXRlKGNodW5rKVxuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHJlc3BvbnNlLnJlbGVhc2UoKVxuIFxuYXN5bmMgZGVmIG1haW4obG9vcCk6XG4gICAgdXJscyA9IFtcImh0dHA6Ly93d3cuaXJzLmdvdi9wdWIvaXJzLXBkZi9mMTA0MC5wZGZcIixcbiAgICAgICAgXCJodHRwOi8vd3d3Lmlycy5nb3YvcHViL2lycy1wZGYvZjEwNDBhLnBkZlwiLFxuICAgICAgICBcImh0dHA6Ly93d3cuaXJzLmdvdi9wdWIvaXJzLXBkZi9mMTA0MGV6LnBkZlwiLFxuICAgICAgICBcImh0dHA6Ly93d3cuaXJzLmdvdi9wdWIvaXJzLXBkZi9mMTA0MGVzLnBkZlwiLFxuICAgICAgICBcImh0dHA6Ly93d3cuaXJzLmdvdi9wdWIvaXJzLXBkZi9mMTA0MHNiLnBkZlwiXVxuIFxuICAgIGFzeW5jIHdpdGggYWlvaHR0cC5DbGllbnRTZXNzaW9uKGxvb3A9bG9vcCkgYXMgc2Vzc2lvbjpcbiAgICAgICAgdGFza3MgPSBbZG93bmxvYWRfY29yb3V0aW5lKHNlc3Npb24sIHVybCkgZm9yIHVybCBpbiB1cmxzXVxuICAgICAgICBhd2FpdCBhc3luY2lvLmdhdGhlcigqdGFza3MpXG4gXG4gXG5pZiBfX25hbWVfXyA9PSAnX19tYWluX18nOlxuICAgIGxvb3AgPSBhc3luY2lvLmdldF9ldmVudF9sb29wKClcbiAgICBsb29wLnJ1bl91bnRpbF9jb21wbGV0ZShtYWluKGxvb3ApKSIsInNjdCI6IkV4KCkudGVzdF9pbXBvcnQoXCJhaW9odHRwXCIpXG5FeCgpLnRlc3RfaW1wb3J0KFwiYXN5bmNpb1wiKVxuRXgoKS50ZXN0X2ltcG9ydChcImFzeW5jX3RpbWVvdXRcIilcbkV4KCkudGVzdF9pbXBvcnQoXCJvc1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJhc3luYyBkZWYgZG93bmxvYWRfY29yb3V0aW5lKHNlc3Npb24sIHVybCk6XCIsIHBhdHRlcm49RmFsc2UsIG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IGRlZmluZSBgYXN5bmMgZGVmIGRvd25sb2FkX2Nvcm91dGluZWAgdGhhdCB0YWtlcyBgc2Vzc2lvbmAgYW5kIGB1cmxgIGFzIGFyZ3VtZW50cz9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwid2l0aCBhc3luY190aW1lb3V0LnRpbWVvdXQoMTApXCIsIHBhdHRlcm49RmFsc2Usbm90X3R5cGVkX21zZz1cIkRpZCB5b3Ugc2V0IHRoZSBhc3luYyB0aW1lb3V0IGF0IGAxMGAgP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJhc3luYyB3aXRoIHNlc3Npb24uZ2V0KHVybCkgYXMgcmVzcG9uc2U6XCIsIHBhdHRlcm49RmFsc2UsIG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IGNhbGwgYHNlc3Npb25gJ3MgYGdldCgpYCBtZXRob2QgdG8gZ2V0IHRoZSBgcmVzcG9uc2VgIG9iamVjdCBiYWNrP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJmaWxlbmFtZSA9IG9zLnBhdGguYmFzZW5hbWUodXJsKVwiLHBhdHRlcm49RmFsc2UsIG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IHNwZWNpZnkgdGhlIGBmaWxlbmFtZWAgdmFyaWFibGUgd2l0aGUgdGhlIGhlbHAgb2YgYG9zLnBhdGguYmFzZW5hbWUoKWAgP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJ3aXRoIG9wZW4oZmlsZW5hbWUsIFxcJ3diXFwnKSBhcyBmX2hhbmRsZTpcIiwgcGF0dGVybj1GYWxzZSwgbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgcGFzcyBgZmlsZW5hbWVgIGFuZCBgJ3diJ2AgdG8gYG9wZW4oKWAgP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJ3aGlsZSBUcnVlXCIsIHBhdHRlcm49RmFsc2Usbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgbGVhdmUgc29tZXRoaW5nIG91dCBvZiB0aGUgY29kZT9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwiY2h1bmsgPSBhd2FpdCByZXNwb25zZS5jb250ZW50LnJlYWQoMTAyNClcIiwgcGF0dGVybj1GYWxzZSwgbm90X3R5cGVkX21zZz1cIkRpZCB5b3Ugc3BlY2lmeSB0aGUgYGNodW5rYCB2YXJpYWJsZT9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwiaWYgbm90IGNodW5rXCIsIHBhdHRlcm49RmFsc2Usbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgbGVhdmUgc29tZXRoaW5nIG91dCBvZiB0aGUgY29kZT9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwiYnJlYWtcIiwgcGF0dGVybj1GYWxzZSxub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBsZWF2ZSBzb21ldGhpbmcgb3V0IG9mIHRoZSBjb2RlP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJmX2hhbmRsZS53cml0ZShjaHVuaylcIiwgcGF0dGVybj1GYWxzZSxub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBwYXNzIGBjaHVua2AgdG8gYGZfaGFuZGxlLndyaXRlKClgP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJyZXR1cm4gYXdhaXQgcmVzcG9uc2UucmVsZWFzZSgpXCIsIHBhdHRlcm49RmFsc2Usbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgbGVhdmUgc29tZXRoaW5nIG91dCBvZiB0aGUgY29kZT9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwiYXN5bmMgZGVmIG1haW4obG9vcCk6XCIsIHBhdHRlcm49RmFsc2Usbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgbGVhdmUgc29tZXRoaW5nIG91dCBvZiB0aGUgY29kZT9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwidXJscyA9IFtcXFwiaHR0cDovL3d3dy5pcnMuZ292L3B1Yi9pcnMtcGRmL2YxMDQwLnBkZlxcXCIsXCIscGF0dGVybj1GYWxzZSwgbm90X3R5cGVkX21zZz1cIk1ha2Ugc3VyZSB0byBwYXNzIGF0IGxlYXN0IDEgdXJsIHRvIHRoZSBgdXJsc2AgdmFyaWFibGUhXCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcIlxcXCJdXCIsIHBhdHRlcm49RmFsc2UsKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJhc3luYyB3aXRoIGFpb2h0dHAuQ2xpZW50U2Vzc2lvbihsb29wPWxvb3ApIGFzIHNlc3Npb246XCIsIHBhdHRlcm49RmFsc2UsIG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IGxlYXZlIHNvbWV0aGluZyBvdXQgb2YgdGhlIGNvZGU/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcInRhc2tzID0gW2Rvd25sb2FkX2Nvcm91dGluZShzZXNzaW9uLCB1cmwpIGZvciB1cmwgaW4gdXJsc11cIiwgcGF0dGVybj1GYWxzZSxub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBsZWF2ZSBzb21ldGhpbmcgb3V0IG9mIHRoZSBjb2RlP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJhd2FpdCBhc3luY2lvLmdhdGhlcigqdGFza3MpXCIsIHBhdHRlcm49RmFsc2Usbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgbGVhdmUgc29tZXRoaW5nIG91dCBvZiB0aGUgY29kZT9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwiaWYgX19uYW1lX18gPT0gXFwnX19tYWluX19cXCc6XCIsIHBhdHRlcm49RmFsc2Usbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgbGVhdmUgc29tZXRoaW5nIG91dCBvZiB0aGUgY29kZT9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwibG9vcCA9IGFzeW5jaW8uZ2V0X2V2ZW50X2xvb3AoKVwiLCBwYXR0ZXJuPUZhbHNlLG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IGluaXRpYWxpemUgYSBgbG9vcGAgb2JqZWN0P1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJsb29wLnJ1bl91bnRpbF9jb21wbGV0ZShtYWluKGxvb3ApKVwiLCBwYXR0ZXJuPUZhbHNlLG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IGxlYXZlIHNvbWV0aGluZyBvdXQgb2YgdGhlIGNvZGU/XCIpXG5zdWNjZXNzX21zZyhcIldlbGwgZG9uZSEgWW91IGhhdmUgbm93IGRvd25sb2FkZWQgdGhlIGZpbGVzIHdpdGggdGhlIGBhaW9odHRwYCBwYWNrYWdlIVwiKSJ9

Hier importieren wir zwei neue Bausteine: aiohttp und async_timeout. Letzteres ist eine Abhängigkeit von aiohttp und ermöglicht uns einen Timeout-Context-Manager. Gehen wir von unten nach oben durch den Code: In der unteren Bedingung starten wir den asynchronen Event-Loop und rufen unsere Main-Funktion auf.

In der Main-Funktion erstellen wir ein ClientSession-Objekt, das wir an unsere Download-Coroutine für jede zu ladende URL übergeben. In download_coroutine erzeugen wir mit async_timeout.timeout() einen Context-Manager, der im Grunde einen Timer von X Sekunden setzt. Läuft die Zeit ab, endet der Context-Manager. Hier beträgt das Timeout 10 Sekunden. Anschließend rufen wir get() auf der Session auf und erhalten ein Response-Objekt. Jetzt kommt der magische Teil: Über das Attribut content des Response-Objekts erhalten wir eine Instanz von aiohttp.StreamReader, mit der wir die Datei in frei wählbaren Chunk-Größen herunterladen können. Während wir lesen, schreiben wir auf die lokale Platte. Zum Schluss rufen wir release() der Response auf, um die Verarbeitung abzuschließen.

Laut aiohttp-Dokumentation wird release() implizit aufgerufen, da das Response-Objekt in einem Context-Manager erstellt wurde. In Python gilt jedoch meist: Explizit ist besser als implizit. Zudem rät die Doku davon ab, sich darauf zu verlassen, dass die Verbindung einfach verschwindet – daher ist es hier besser, explizit zu releasen.

Ein Teil blockiert hier weiterhin: das Schreiben auf die Festplatte. Während des Schreibens blockieren wir noch. Es gibt eine weitere Bibliothek namens aiofiles, mit der sich auch das Dateischreiben asynchronisieren ließe. Dieses Update überlasse ich dir.

Aufrufe planen

Du kannst mit dem asyncio-Event-Loop auch Aufrufe regulärer Funktionen planen. Die erste Methode ist call_soon. Sie ruft deinen Callback bzw. Event-Handler so schnell wie möglich auf. Die Ausführung folgt einer FIFO-Warteschlange. Dauern einige Callbacks länger, verzögern sich die nachfolgenden, bis die vorherigen fertig sind.

Ein Beispiel:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImltcG9ydCBfX19fX19cbmltcG9ydCBmdW5jdG9vbHNcbiBcbmRlZiBldmVudF9oYW5kbGVyKGxvb3AsIHN0b3A9RmFsc2UpOlxuICAgIHByaW50KCdFdmVudCBoYW5kbGVyIGNhbGxlZCcpXG4gICAgaWYgc3RvcDpcbiAgICAgICAgcHJpbnQoJ3N0b3BwaW5nIHRoZSBsb29wJylcbiAgICAgICAgbG9vcC5zdG9wKClcblxuaWYgX19uYW1lX18gPT0gJ19fbWFpbl9fJzpcbiAgICBsb29wID0gYXN5bmNpby5nZXRfZXZlbnRfbG9vcCgpXG4gICAgdHJ5OlxuICAgICAgICBsb29wLmNhbGxfc29vbihmdW5jdG9vbHMucGFydGlhbChfX19fX19fX19fX19fLCBfX19fKSlcbiAgICAgICAgcHJpbnQoJ3N0YXJ0aW5nIGV2ZW50IGxvb3AnKVxuICAgICAgICBsb29wLmNhbGxfc29vbihmdW5jdG9vbHMucGFydGlhbChfX19fX19fX19fX19fLCBfX19fLCBzdG9wPVRydWUpKVxuIFxuICAgICAgICBsb29wLl9fX19fX19fX18oKVxuICAgIGZpbmFsbHk6XG4gICAgICAgIHByaW50KCdjbG9zaW5nIGV2ZW50IGxvb3AnKVxuICAgICAgICBsb29wLl9fX19fKCkiLCJzb2x1dGlvbiI6ImltcG9ydCBhc3luY2lvXG5pbXBvcnQgZnVuY3Rvb2xzXG4gXG5kZWYgZXZlbnRfaGFuZGxlcihsb29wLCBzdG9wPUZhbHNlKTpcbiAgICBwcmludCgnRXZlbnQgaGFuZGxlciBjYWxsZWQnKVxuICAgIGlmIHN0b3A6XG4gICAgICAgIHByaW50KCdzdG9wcGluZyB0aGUgbG9vcCcpXG4gICAgICAgIGxvb3Auc3RvcCgpXG5cbmlmIF9fbmFtZV9fID09ICdfX21haW5fXyc6XG4gICAgbG9vcCA9IGFzeW5jaW8uZ2V0X2V2ZW50X2xvb3AoKVxuICAgIHRyeTpcbiAgICAgICAgbG9vcC5jYWxsX3Nvb24oZnVuY3Rpb2xzLnBhcnRpYWwoZXZlbnRfaGFuZGxlciwgbG9vcCkpXG4gICAgICAgIHByaW50KCdzdGFydGluZyBldmVudCBsb29wJylcbiAgICAgICAgbG9vcC5jYWxsX3Nvb24oZnVuY3Rpb2xzLnBhcnRpYWwoZXZlbnRfaGFuZGxlciwgbG9vcCwgc3RvcD1UcnVlKSlcbiBcbiAgICAgICAgbG9vcC5ydW5fZm9yZXZlcigpXG4gICAgZmluYWxseTpcbiAgICAgICAgcHJpbnQoJ2Nsb3NpbmcgZXZlbnQgbG9vcCcpXG4gICAgICAgIGxvb3AuY2xvc2UoKSIsInNjdCI6IkV4KCkudGVzdF9pbXBvcnQoXCJhc3luY2lvXCIpXG5FeCgpLnRlc3RfaW1wb3J0KFwiZnVuY3Rvb2xzXCIpXG5FeCgpLnRlc3RfZnVuY3Rpb25fZGVmaW5pdGlvbihcImV2ZW50X2hhbmRsZXJcIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwiaWYgX19uYW1lX18gPT0gXFwnX19tYWluX19cXCc6XCIsIHBhdHRlcm49RmFsc2UsIG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IHJlbW92ZSBzb21ldGhpbmcgZnJvbSB0aGUgY29kZTE/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcImxvb3AgPSBhc3luY2lvLmdldF9ldmVudF9sb29wKClcIiwgcGF0dGVybj1GYWxzZSxub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBhc3NpZ24gYGFzeW5jaW8uZ2V0X2V2ZW50X2xvb3AoKWAgdG8gYGxvb3BgP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJ0cnk6XCIsIHBhdHRlcm49RmFsc2Usbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgYWRkIGB0cnlgIHRvIHRoZSBjb2RlP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJsb29wLmNhbGxfc29vbihmdW5jdG9vbHMucGFydGlhbChldmVudF9oYW5kbGVyLCBsb29wKSlcIiwgcGF0dGVybj1GYWxzZSwgbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgcGFzcyBgZXZlbnRfaGFuZGxlcmAgYW5kIGBsb29wYCB0byBgbG9vcC5jYWxsX3Nvb24oZnVuY3Rpb2xzLnBhcnRpYWwoKSlgP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJsb29wLmNhbGxfc29vbihmdW5jdG9vbHMucGFydGlhbChldmVudF9oYW5kbGVyLCBsb29wLCBzdG9wPVRydWUpKVwiLCBwYXR0ZXJuPUZhbHNlLCBub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBwYXNzIGBldmVudF9oYW5kbGVyYCBhbmQgYGxvb3BgIHRvIGBsb29wLmNhbGxfc29vbihmdW5jdGlvbnMucGFydGlhbCgpKWA/IERvbid0IGZvcmdldCB0byBrZWVwIGBzdG9wYCBzZXQgdG8gYFRydWVgIVwiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJsb29wLnJ1bl9mb3JldmVyKClcIiwgcGF0dGVybj1GYWxzZSxub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBhZGQgYGxvb3AucnVuX2ZvcmV2ZXIoKWAgdG8gdGhlIGNvZGU/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcImZpbmFsbHk6XCIsIHBhdHRlcm49RmFsc2Usbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgYWRkIGBmaW5hbGx5YCB0byB0aGUgY29kZT9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwibG9vcC5jbG9zZSgpXCIsIHBhdHRlcm49RmFsc2Usbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgY2xvc2UgYGxvb3BgP1wiKVxuc3VjY2Vzc19tc2coXCJZb3UgaGF2ZSBub3cgc3VjY2Vzc2Z1bGx5IGxlYXJuZWQgaG93IHRvIHNjaGVkdWxlIGNhbGxzIHdpdGggdGhlIGFzeW5jaW8gZXZlbnQgbG9vcCFcIikifQ==

Die meisten Funktionen von asyncio akzeptieren keine Keyword-Argumente, daher brauchen wir für Schlüsselwörter das Modul functools. Unsere reguläre Funktion schreibt bei jedem Aufruf Text auf stdout. Setzt du das Argument stop auf True, stoppt sie außerdem den Event-Loop.

Beim ersten Aufruf stoppen wir den Loop nicht. Beim zweiten Aufruf stoppen wir ihn. Das ist nötig, weil wir run_forever aufgerufen haben – der Event-Loop würde sonst endlos laufen. Ist der Loop gestoppt, können wir ihn schließen.

Wenn du den Code startest, solltest du diese Ausgabe sehen:

starting event loop
Event handler called
Event handler called
stopping the loop
closing event loop

Verwandt ist die Funktion call_soon_threadsafe. Wie der Name vermuten lässt, funktioniert sie wie call_soon, ist aber thread-sicher. Wenn du einen Aufruf gezielt verzögern möchtest, kannst du call_later verwenden. In unserem Beispiel könnten wir die call_soon-Signatur so ändern:

loop.call_later(1, event_handler, loop)

Damit verzögern wir den Aufruf unseres Event-Handlers um eine Sekunde; anschließend wird er aufgerufen und erhält den Loop als ersten Parameter. Möchtest du einen konkreten Zeitpunkt in der Zukunft planen, nimm die Zeit des Loops statt der Systemzeit. So geht’s:

current_time = loop.time()

Dann kannst du call_at verwenden und die gewünschte Zeit übergeben. Angenommen, wir wollen den Event-Handler in fünf Minuten aufrufen. So könnte das aussehen:

loop.call_at(current_time + 300, event_handler, loop)

Hier nehmen wir die aktuelle Loop-Zeit und addieren 300 Sekunden bzw. fünf Minuten. So verzögern wir den Aufruf unseres Event-Handlers um fünf Minuten. Ziemlich praktisch!

Tasks

Tasks sind eine Unterklasse von Future und ein Wrapper um eine Coroutine. Sie ermöglichen es dir, nachzuvollziehen, wann die Verarbeitung abgeschlossen ist. Da sie eine Future sind, können andere Coroutinen auf eine Task warten, und du kannst das Ergebnis einer fertig verarbeiteten Task abrufen.

Ein einfaches Beispiel:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImltcG9ydCBfX19fX19fXG5cbmFzeW5jIGRlZiBteV90YXNrKHNlY29uZHMpOlxuICAgIFwiXCJcIlxuICAgIEEgdGFzayB0byBkbyBmb3IgYSBudW1iZXIgb2Ygc2Vjb25kc1xuICAgIFwiXCJcIlxuICAgIHByaW50KCdUaGlzIHRhc2sgaXMgdGFraW5nIHt9IHNlY29uZHMgdG8gY29tcGxldGUnLmZvcm1hdChcbiAgICAgICAgc2Vjb25kcykpXG4gICAgYXdhaXQgYXN5bmNpby5zbGVlcChfX19fX19fKVxuICAgIHJldHVybiAndGFzayBmaW5pc2hlZCdcbiBcbiBcbmlmIF9fbmFtZV9fID09ICdfX21haW5fXyc6XG4gICAgbXlfZXZlbnRfbG9vcCA9IGFzeW5jaW8uZ2V0X2V2ZW50X2xvb3AoKVxuICAgIHRyeTpcbiAgICAgICAgcHJpbnQoJ3Rhc2sgY3JlYXRpb24gc3RhcnRlZCcpXG4gICAgICAgIHRhc2tfb2JqID0gbXlfZXZlbnRfbG9vcC5jcmVhdGVfdGFzayhteV90YXNrKHNlY29uZHM9MikpXG4gICAgICAgIG15X2V2ZW50X2xvb3AucnVuX3VudGlsX2NvbXBsZXRlKHRhc2tfb2JqKVxuICAgIGZpbmFsbHk6XG4gICAgICAgIG15X2V2ZW50X2xvb3AuX19fX18oKVxuIFxuICAgIHByaW50KFwiVGhlIHRhc2sncyByZXN1bHQgd2FzOiB7fVwiLmZvcm1hdCh0YXNrX29iai5yZXN1bHQoKSkpIiwic29sdXRpb24iOiJpbXBvcnQgYXN5bmNpb1xuXG5hc3luYyBkZWYgbXlfdGFzayhzZWNvbmRzKTpcbiAgICBcIlwiXCJcbiAgICBBIHRhc2sgdG8gZG8gZm9yIGEgbnVtYmVyIG9mIHNlY29uZHNcbiAgICBcIlwiXCJcbiAgICBwcmludCgnVGhpcyB0YXNrIGlzIHRha2luZyB7fSBzZWNvbmRzIHRvIGNvbXBsZXRlJy5mb3JtYXQoc2Vjb25kcykpXG4gICAgYXdhaXQgYXN5bmNpby5zbGVlcChzZWNvbmRzKVxuICAgIHJldHVybiAndGFzayBmaW5pc2hlZCdcbiBcbiBcbmlmIF9fbmFtZV9fID09ICdfX21haW5fXyc6XG4gICAgbXlfZXZlbnRfbG9vcCA9IGFzeW5jaW8uZ2V0X2V2ZW50X2xvb3AoKVxuICAgIHRyeTpcbiAgICAgICAgcHJpbnQoJ3Rhc2sgY3JlYXRpb24gc3RhcnRlZCcpXG4gICAgICAgIHRhc2tfb2JqID0gbXlfZXZlbnRfbG9vcC5jcmVhdGVfdGFzayhteV90YXNrKHNlY29uZHM9MikpXG4gICAgICAgIG15X2V2ZW50X2xvb3AucnVuX3VudGlsX2NvbXBsZXRlKHRhc2tfb2JqKVxuICAgIGZpbmFsbHk6XG4gICAgICAgIG15X2V2ZW50X2xvb3AuY2xvc2UoKVxuIFxuICAgIHByaW50KFwiVGhlIHRhc2sncyByZXN1bHQgd2FzOiB7fVwiLmZvcm1hdCh0YXNrX29iai5yZXN1bHQoKSkpIiwic2N0IjoiRXgoKS50ZXN0X2ltcG9ydChcImFzeW5jaW9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwiYXN5bmMgZGVmIG15X3Rhc2soc2Vjb25kcyk6XCIsIHBhdHRlcm49RmFsc2UsIG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IGRlZmluZSB0aGUgYXN5bmMgZnVuY3Rpb24gYG15X3Rhc2soKWA/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcImF3YWl0IGFzeW5jaW8uc2xlZXAoc2Vjb25kcylcIiwgcGF0dGVybj1GYWxzZSwgbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgcGFzcyBgc2Vjb25kc2AgdG8gYGFzeW5jaW8uc2xlZXAoKWA/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcInJldHVybiBcXCd0YXNrIGZpbmlzaGVkXFwnXCIsIHBhdHRlcm49RmFsc2UsIG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IHJldHVybiBcXCd0YXNrIGZpbmlzaGVkXFwnP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJpZiBfX25hbWVfXyA9PSBcXCdfX21haW5fX1xcJzpcIiwgcGF0dGVybj1GYWxzZSwgbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgcmVtb3ZlIHNvbWV0aGluZyBmcm9tIHRoZSBjb2RlP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJteV9ldmVudF9sb29wID0gYXN5bmNpby5nZXRfZXZlbnRfbG9vcCgpXCIsIHBhdHRlcm49RmFsc2UsIG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IGdldCB0aGUgZXZlbnQgbG9vcCB3aXRoIGBnZXRfZXZlbnRfbG9vcCgpYCBhbmQgYXNzaWduIGl0IHRvIGBteV9ldmVudF9sb29wYD9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwidHJ5OlwiLCBwYXR0ZXJuPUZhbHNlLCBub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBhZGQgYHRyeWAgdG8gdGhlIGNvZGUgY2h1bms/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcInRhc2tfb2JqID0gbXlfZXZlbnRfbG9vcC5jcmVhdGVfdGFzayhteV90YXNrKHNlY29uZHM9MikpXCIsIHBhdHRlcm49RmFsc2UsIG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IGNyZWF0ZSBhIHRhc2sgZm9yIGBteV9ldmVudF9sb29wYCB3aXRoIGBjcmVhdGVfdGFza2A/IEFsc28gZG9uJ3QgZm9yZ2V0IHRvIHBhc3MgYG15X3Rhc2soc2Vjb25kcz0yKWAgdG8gdGhlIGZ1bmN0aW9uIVwiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJteV9ldmVudF9sb29wLnJ1bl91bnRpbF9jb21wbGV0ZSh0YXNrX29iailcIiwgcGF0dGVybj1GYWxzZSwgbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgYWRkIGBteV9ldmVudF9sb29wLnJ1bl91bnRpbF9jb21wbGV0ZSh0YXNrX29iaikgdG8gdGhlIGNvZGUgY2h1bms/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcImZpbmFsbHk6XCIsIHBhdHRlcm49RmFsc2UsIG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IHNwZWNpZnkgYGZpbmFsbHlgP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJteV9ldmVudF9sb29wLmNsb3NlKClcIiwgcGF0dGVybj1GYWxzZSwgbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgY2xvc2UgYG15X2V2ZW50X2xvb3BgIHdpdGggYGNsb3NlKClgP1wiKVxuc3VjY2Vzc19tc2coXCJDb25ncmF0cyEgWW91IGhhdmUgY3JlYXRlZCBhbiBhc3luYyBmdW5jdGlvbiB0aGF0IGFjY2VwdHMgdGhlIG51bWJlciBvZiBzZWNvbmRzIGl0IHdpbGwgdGFrZSBmb3IgdGhlIGZ1bmN0aW9uIHRvIHJ1biFcIikifQ==

Hier definieren wir eine asynchrone Funktion, die die Anzahl der Sekunden entgegennimmt, die sie „laufen“ soll – als Simulation eines lang laufenden Prozesses. Dann erstellen wir den Event-Loop und erzeugen mit dessen create_task eine Task. create_task nimmt die Funktion entgegen, die wir als Task ausführen wollen. Anschließend lassen wir den Event-Loop laufen, bis die Task abgeschlossen ist. Am Ende holen wir uns das Ergebnis der Task.

Tasks lassen sich außerdem sehr leicht mit ihrer cancel-Methode abbrechen. Ruf sie einfach auf, wenn du eine Task beenden willst. Wird eine Task während des Wartens auf eine andere Operation abgebrochen, wirft sie eine CancelledError.

Fazit

Jetzt kennst du genug, um mit der Bibliothek asyncio eigenständig zu arbeiten. asyncio ist sehr mächtig und ermöglicht dir eine Menge spannender Aufgaben. Die asyncio-Bibliothek wurde für Netzwerksockets konzipiert.

Eine großartige Bibliothek für asynchrones Socket-Programming vor asyncio ist das Twisted-Framework. Ein weiteres spannendes Projekt ist Dask, eine flexible Bibliothek für paralleles Rechnen in der Analytik. Stöbere in der Dokumentation zum asyncio-Modul und lass deinen Ideen freien Lauf!

Themen
Python

Python-Kurse

Kurs

Einführung in Python

4 Std.
7M
Lerne in nur vier Stunden die Grundlagen der Datenanalyse mit Python und entdecke beliebte Python-Pakete.
Details anzeigenRight Arrow
Kurs Starten
Mehr anzeigenRight Arrow