Event Loop

Quellcode: Lib/asyncio/events.py, Lib/asyncio/base_events.py


Vorwort

Die Event-Schleife ist der Kern jeder asyncio-Anwendung. Event-Schleifen führen asynchrone Tasks und Callbacks aus, führen Netzwerk-I/O-Operationen durch und führen Subprozesse aus.

Anwendungsentwickler sollten in der Regel die High-Level-Funktionen von asyncio verwenden, wie z. B. asyncio.run(), und sollten selten auf das Schleifenobjekt verweisen oder dessen Methoden aufrufen müssen. Dieser Abschnitt richtet sich hauptsächlich an Autoren von Low-Level-Code, Bibliotheken und Frameworks, die eine feinere Kontrolle über das Verhalten der Event-Schleife benötigen.

Die Event Loop erhalten

Die folgenden Low-Level-Funktionen können verwendet werden, um eine Event-Schleife abzurufen, festzulegen oder zu erstellen

asyncio.get_running_loop()

Gibt die laufende Event-Schleife im aktuellen Betriebssystem-Thread zurück.

Löst einen RuntimeError aus, wenn keine laufende Event-Schleife vorhanden ist.

Diese Funktion kann nur von einem Korutin oder einem Callback aufgerufen werden.

Hinzugefügt in Version 3.7.

asyncio.get_event_loop()

Holt die aktuelle Event-Schleife.

Wenn von einer Korutin oder einem Callback aufgerufen (z. B. geplant mit call_soon oder ähnlicher API), gibt diese Funktion immer die laufende Event-Schleife zurück.

Wenn keine laufende Event-Schleife gesetzt ist, gibt die Funktion das Ergebnis des Aufrufs get_event_loop_policy().get_event_loop() zurück.

Da diese Funktion ein recht komplexes Verhalten aufweist (insbesondere bei benutzerdefinierten Event-Loop-Richtlinien), ist die Verwendung der Funktion get_running_loop() für Korutinen und Callbacks der Funktion get_event_loop() vorzuziehen.

Wie oben erwähnt, sollten Sie die High-Level-Funktion asyncio.run() in Betracht ziehen, anstatt diese Low-Level-Funktionen zum manuellen Erstellen und Schließen einer Event-Schleife zu verwenden.

Geändert in Version 3.14: Löst einen RuntimeError aus, wenn keine aktuelle Event-Schleife vorhanden ist.

Hinweis

Das Richtliniensystem von asyncio ist veraltet und wird in Python 3.16 entfernt. Ab dann gibt diese Funktion die aktuelle laufende Event-Schleife zurück, falls vorhanden, andernfalls gibt sie die Schleife zurück, die von set_event_loop() gesetzt wurde.

asyncio.set_event_loop(loop)

Setzt loop als die aktuelle Event-Schleife für den aktuellen Betriebssystem-Thread.

asyncio.new_event_loop()

Erstellt und gibt ein neues Event-Loop-Objekt zurück.

Beachten Sie, dass das Verhalten der Funktionen get_event_loop(), set_event_loop() und new_event_loop() durch das Festlegen einer benutzerdefinierten Event-Loop-Richtlinie geändert werden kann.

Inhalt

Diese Dokumentationsseite enthält die folgenden Abschnitte

Event Loop Methods

Event-Schleifen haben **Low-Level**-APIs für Folgendes

Schleife ausführen und stoppen

loop.run_until_complete(future)

Läuft, bis der future (eine Instanz von Future) abgeschlossen ist.

Wenn das Argument ein Korutin-Objekt ist, wird es implizit als asyncio.Task geplant.

Gibt das Ergebnis des Future zurück oder löst dessen Ausnahme aus.

loop.run_forever()

Führt die Event-Schleife aus, bis stop() aufgerufen wird.

Wenn stop() aufgerufen wird, bevor run_forever() aufgerufen wird, pollt die Schleife einmal den I/O-Selektor mit einem Timeout von Null, führt alle Callbacks aus, die als Reaktion auf I/O-Ereignisse geplant wurden (und die, die bereits geplant waren), und beendet sich dann.

Wenn stop() aufgerufen wird, während run_forever() läuft, führt die Schleife den aktuellen Satz von Callbacks aus und beendet sich dann. Beachten Sie, dass neu geplante Callbacks in diesem Fall nicht ausgeführt werden; stattdessen werden sie beim nächsten Aufruf von run_forever() oder run_until_complete() ausgeführt.

loop.stop()

Stoppt die Event-Schleife.

loop.is_running()

Gibt True zurück, wenn die Event-Schleife gerade ausgeführt wird.

loop.is_closed()

Gibt True zurück, wenn die Event-Schleife geschlossen wurde.

loop.close()

Schließt die Event-Schleife.

Die Schleife darf beim Aufruf dieser Funktion nicht ausgeführt werden. Alle ausstehenden Callbacks werden verworfen.

Diese Methode leert alle Warteschlangen und fährt den Executor herunter, wartet jedoch nicht darauf, dass der Executor seine Ausführung beendet.

Diese Methode ist idempotent und unwiderruflich. Nach dem Schließen der Event-Schleife sollten keine anderen Methoden mehr aufgerufen werden.

async loop.shutdown_asyncgens()

Plant, alle aktuell geöffneten asynchronen Generator-Objekte mit einem Aufruf von aclose() zu schließen. Nach dem Aufruf dieser Methode gibt die Event-Schleife eine Warnung aus, wenn ein neuer asynchroner Generator iteriert wird. Dies sollte verwendet werden, um alle geplanten asynchronen Generatoren zuverlässig zu finalisieren.

Beachten Sie, dass diese Funktion nicht aufgerufen werden muss, wenn asyncio.run() verwendet wird.

Beispiel

try:
    loop.run_forever()
finally:
    loop.run_until_complete(loop.shutdown_asyncgens())
    loop.close()

Hinzugefügt in Version 3.6.

async loop.shutdown_default_executor(timeout=None)

Plant das Schließen des Standard-Executors und wartet darauf, dass er alle Threads im ThreadPoolExecutor zusammenführt. Nach dem Aufruf dieser Methode löst die Verwendung des Standard-Executors mit loop.run_in_executor() einen RuntimeError aus.

Der Parameter timeout gibt an, wie viel Zeit (in float Sekunden) der Executor zum Beenden des Zusammenführens erhält. Mit dem Standardwert None darf der Executor unbegrenzt viel Zeit beanspruchen.

Wenn der timeout erreicht wird, wird eine RuntimeWarning ausgegeben und der Standard-Executor wird beendet, ohne darauf zu warten, dass seine Threads zusammengeführt werden.

Hinweis

Rufen Sie diese Methode nicht auf, wenn asyncio.run() verwendet wird, da letztere das Herunterfahren des Standard-Executors automatisch handhabt.

Hinzugefügt in Version 3.9.

Geändert in Version 3.12: Der Parameter timeout wurde hinzugefügt.

Callbacks planen

loop.call_soon(callback, *args, context=None)

Plant, dass der callback Callback mit den args Argumenten bei der nächsten Iteration der Event-Schleife aufgerufen wird.

Gibt eine Instanz von asyncio.Handle zurück, die später zum Abbrechen des Callbacks verwendet werden kann.

Callbacks werden in der Reihenfolge aufgerufen, in der sie registriert werden. Jeder Callback wird genau einmal aufgerufen.

Das optionale schlüsselwort-nur context Argument gibt einen benutzerdefinierten contextvars.Context an, in dem der callback ausgeführt werden soll. Callbacks verwenden den aktuellen Kontext, wenn kein context angegeben wird.

Im Gegensatz zu call_soon_threadsafe() ist diese Methode nicht threadsicher.

loop.call_soon_threadsafe(callback, *args, context=None)

Eine threadsichere Variante von call_soon(). Beim Planen von Callbacks aus einem anderen Thread *muss* diese Funktion verwendet werden, da call_soon() nicht threadsicher ist.

Diese Funktion ist sicher aus einem reentranten Kontext oder Signalhandler aufrufbar, jedoch ist es nicht sicher oder nützlich, das zurückgegebene Handle in solchen Kontexten zu verwenden.

Löst RuntimeError aus, wenn sie auf einer geschlossenen Schleife aufgerufen wird. Dies kann auf einem sekundären Thread geschehen, wenn die Hauptanwendung heruntergefahren wird.

Siehe den Abschnitt über Nebenläufigkeit und Multithreading in der Dokumentation.

Geändert in Version 3.7: Der schlüsselwort-nur Parameter context wurde hinzugefügt. Siehe PEP 567 für weitere Details.

Hinweis

Die meisten asyncio-Planungsfunktionen erlauben keine Übergabe von Schlüsselwortargumenten. Verwenden Sie hierfür functools.partial()

# will schedule "print("Hello", flush=True)"
loop.call_soon(
    functools.partial(print, "Hello", flush=True))

Die Verwendung von Partial-Objekten ist normalerweise bequemer als die Verwendung von Lambdas, da asyncio Partial-Objekte in Debug- und Fehlermeldungen besser darstellen kann.

Verzögerte Callbacks planen

Die Event-Schleife bietet Mechanismen, um Callback-Funktionen zu planen, die zu einem späteren Zeitpunkt ausgeführt werden sollen. Die Event-Schleife verwendet mononische Uhren, um die Zeit zu verfolgen.

loop.call_later(delay, callback, *args, context=None)

Plant, dass callback nach der angegebenen delay Anzahl von Sekunden (kann eine Ganzzahl oder eine Gleitkommazahl sein) aufgerufen wird.

Eine Instanz von asyncio.TimerHandle wird zurückgegeben, die zum Abbrechen des Callbacks verwendet werden kann.

callback wird genau einmal aufgerufen. Wenn zwei Callbacks für genau dieselbe Zeit geplant sind, ist die Reihenfolge, in der sie aufgerufen werden, undefiniert.

Die optionalen positionsbezogenen args werden an den Callback übergeben, wenn er aufgerufen wird. Wenn Sie möchten, dass der Callback mit Schlüsselwortargumenten aufgerufen wird, verwenden Sie functools.partial().

Ein optionales schlüsselwort-nur context Argument erlaubt die Angabe eines benutzerdefinierten contextvars.Context, in dem der callback ausgeführt werden soll. Der aktuelle Kontext wird verwendet, wenn kein context angegeben wird.

Hinweis

Aus Performance-Gründen können Callbacks, die mit loop.call_later() geplant wurden, bis zu einer Takt-Auflösung frühzeitig ausgeführt werden (siehe time.get_clock_info('monotonic').resolution).

Geändert in Version 3.7: Der schlüsselwort-nur Parameter context wurde hinzugefügt. Siehe PEP 567 für weitere Details.

Geändert in Version 3.8: In Python 3.7 und früheren Versionen mit der Standard-Event-Loop-Implementierung konnte die delay nicht länger als ein Tag sein. Dies wurde in Python 3.8 behoben.

loop.call_at(when, callback, *args, context=None)

Plant, dass callback zum angegebenen absoluten Zeitstempel when (eine Ganzzahl oder Gleitkommazahl) aufgerufen wird, unter Verwendung derselben Zeitreferenz wie loop.time().

Das Verhalten dieser Methode ist dasselbe wie bei call_later().

Eine Instanz von asyncio.TimerHandle wird zurückgegeben, die zum Abbrechen des Callbacks verwendet werden kann.

Hinweis

Aus Performance-Gründen können Callbacks, die mit loop.call_at() geplant wurden, bis zu einer Takt-Auflösung frühzeitig ausgeführt werden (siehe time.get_clock_info('monotonic').resolution).

Geändert in Version 3.7: Der schlüsselwort-nur Parameter context wurde hinzugefügt. Siehe PEP 567 für weitere Details.

Geändert in Version 3.8: In Python 3.7 und früheren Versionen mit der Standard-Event-Loop-Implementierung konnte die Differenz zwischen when und der aktuellen Zeit nicht länger als ein Tag sein. Dies wurde in Python 3.8 behoben.

loop.time()

Gibt die aktuelle Zeit als Gleitkommazahl zurück, gemäß der internen mononischen Uhr der Event-Schleife.

Hinweis

Geändert in Version 3.8: In Python 3.7 und früheren Versionen durften Timeouts (relative delay oder absolute when) nicht länger als ein Tag sein. Dies wurde in Python 3.8 behoben.

Siehe auch

Die Funktion asyncio.sleep().

Futures und Tasks erstellen

loop.create_future()

Erstellt ein asyncio.Future-Objekt, das an die Event-Schleife gebunden ist.

Dies ist der bevorzugte Weg, Futures in asyncio zu erstellen. Dies ermöglicht Drittanbieter-Event-Schleifen, alternative Implementierungen des Future-Objekts bereitzustellen (mit besserer Leistung oder Instrumentierung).

Hinzugefügt in Version 3.5.2.

loop.create_task(coro, *, name=None, context=None, eager_start=None, **kwargs)

Plant die Ausführung der Korutin coro. Gibt ein Task-Objekt zurück.

Drittanbieter-Event-Schleifen können ihre eigenen Unterklassen von Task für die Interoperabilität verwenden. In diesem Fall ist der Ergebnistyp eine Unterklasse von Task.

Die vollständige Funktionssignatur ist weitgehend dieselbe wie die des Konstruktors von Task (oder Factory) – alle Schlüsselwortargumente dieser Funktion werden an diese Schnittstelle weitergegeben.

Wenn das Argument name angegeben und nicht None ist, wird es als Name des Tasks mit Task.set_name() gesetzt.

Ein optionales schlüsselwort-nur context Argument erlaubt die Angabe eines benutzerdefinierten contextvars.Context, in dem coro ausgeführt werden soll. Die aktuelle Kontextkopie wird erstellt, wenn kein context angegeben wird.

Ein optionales schlüsselwort-nur eager_start Argument erlaubt die Angabe, ob der Task beim Aufruf von create_task sofort ausgeführt werden soll oder später geplant werden soll. Wenn eager_start nicht übergeben wird, wird der Modus verwendet, der von loop.set_task_factory() festgelegt wurde.

Geändert in Version 3.8: Der Parameter name wurde hinzugefügt.

Geändert in Version 3.11: Der Parameter context wurde hinzugefügt.

Geändert in Version 3.13.3: kwargs hinzugefügt, die beliebige zusätzliche Parameter übergibt, einschließlich name und context.

Geändert in Version 3.13.4: Die Änderung, die name und context übergibt (wenn sie None sind), wurde zurückgenommen, während andere beliebige Schlüsselwortargumente weiterhin übergeben werden (um die Abwärtskompatibilität mit 3.13.3 nicht zu brechen).

Geändert in Version 3.14: Alle kwargs werden jetzt weitergegeben. Der Parameter eager_start funktioniert mit eager Task-Factories.

loop.set_task_factory(factory)

Setzt eine Task-Factory, die von loop.create_task() verwendet wird.

Wenn factory None ist, wird die Standard-Task-Factory gesetzt. Andernfalls muss factory ein Callable mit der Signatur sein, die mit (loop, coro, **kwargs) übereinstimmt, wobei loop eine Referenz auf die aktive Ereignisschleife ist und coro ein Coroutine-Objekt ist. Das Callable muss alle kwargs weitergeben und ein asyncio.Task-kompatibles Objekt zurückgeben.

Geändert in Version 3.13.3: Erfordert, dass alle kwargs an asyncio.Task weitergegeben werden.

Geändert in Version 3.13.4: name wird nicht mehr an Task-Factories übergeben. context wird nicht mehr an Task-Factories übergeben, wenn es None ist.

Geändert in Version 3.14: name und context werden jetzt wieder bedingungslos an Task-Factories übergeben.

loop.get_task_factory()

Gibt eine Task-Factory zurück oder None, wenn die Standard-Factory verwendet wird.

Netzwerkverbindungen öffnen

async loop.create_connection(protocol_factory, host=None, port=None, *, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, happy_eyeballs_delay=None, interleave=None, all_errors=False)

Öffnet eine Streaming-Transportverbindung zu einer bestimmten Adresse, die durch host und port angegeben ist.

Die Socket-Familie kann entweder AF_INET oder AF_INET6 sein, abhängig von host (oder dem Argument family, falls angegeben).

Der Socket-Typ ist SOCK_STREAM.

protocol_factory muss ein Callable sein, das eine asyncio-Protokoll-Implementierung zurückgibt.

Diese Methode versucht, die Verbindung im Hintergrund herzustellen. Bei Erfolg gibt sie ein (transport, protocol) Paar zurück.

Der chronologische Ablauf der zugrunde liegenden Operation ist wie folgt:

  1. Die Verbindung wird hergestellt und ein Transport dafür erstellt.

  2. protocol_factory wird ohne Argumente aufgerufen und sollte eine Instanz eines Protokolls zurückgeben.

  3. Die Protokollinstanz wird mit dem Transport gekoppelt, indem ihre Methode connection_made() aufgerufen wird.

  4. Ein Tupel (transport, protocol) wird bei Erfolg zurückgegeben.

Der erstellte Transport ist ein implementierungsabhängiger bidirektionaler Stream.

Weitere Argumente

  • ssl: Wenn gegeben und nicht falsch, wird ein SSL/TLS-Transport erstellt (standardmäßig wird ein einfacher TCP-Transport erstellt). Wenn ssl ein ssl.SSLContext-Objekt ist, wird dieser Kontext zur Erstellung des Transports verwendet; wenn ssl True ist, wird ein Standardkontext von ssl.create_default_context() verwendet.

  • server_hostname legt den Hostnamen fest oder überschreibt ihn, gegen den das Zertifikat des Zielservers abgeglichen wird. Sollte nur übergeben werden, wenn ssl nicht None ist. Standardmäßig wird der Wert des Arguments host verwendet. Wenn host leer ist, gibt es keinen Standardwert und Sie müssen einen Wert für server_hostname übergeben. Wenn server_hostname ein leerer String ist, wird der Abgleich des Hostnamens deaktiviert (was ein ernstes Sicherheitsrisiko darstellt und potenzielle Man-in-the-Middle-Angriffe ermöglicht).

  • family, proto, flags sind die optionalen Adressfamilie, das Protokoll und die Flags, die zur Auflösung von host an getaddrinfo() übergeben werden. Falls angegeben, sollten dies alles Ganzzahlen aus den entsprechenden Konstanten des socket-Moduls sein.

  • happy_eyeballs_delay, falls angegeben, aktiviert Happy Eyeballs für diese Verbindung. Es sollte eine Gleitkommazahl sein, die die Wartezeit in Sekunden angibt, bis ein Verbindungsversuch abgeschlossen ist, bevor der nächste Versuch parallel gestartet wird. Dies ist die "Connection Attempt Delay", wie in RFC 8305 definiert. Ein sinnvoller Standardwert, der von der RFC empfohlen wird, ist 0.25 (250 Millisekunden).

  • interleave steuert die Adressreihenfolge, wenn ein Hostname mehrere IP-Adressen auflöst. Wenn 0 oder nicht angegeben, erfolgt keine Neuordnung und die Adressen werden in der von getaddrinfo() zurückgegebenen Reihenfolge versucht. Wenn eine positive Ganzzahl angegeben wird, werden die Adressen nach Adressfamilie verschachtelt und die angegebene Ganzzahl wird als "First Address Family Count" gemäß RFC 8305 interpretiert. Der Standardwert ist 0, wenn happy_eyeballs_delay nicht angegeben ist, und 1, wenn es angegeben ist.

  • sock, falls gegeben, sollte ein vorhandenes, bereits verbundenes socket.socket-Objekt sein, das vom Transport verwendet wird. Wenn sock gegeben ist, sollten host, port, family, proto, flags, happy_eyeballs_delay, interleave und local_addr nicht angegeben werden.

    Hinweis

    Das Argument sock überträgt das Eigentum am Socket an den erstellten Transport. Um den Socket zu schließen, rufen Sie die Methode close() des Transports auf.

  • local_addr, falls gegeben, ist ein Tupel (local_host, local_port), das zum lokalen Binden des Sockets verwendet wird. local_host und local_port werden ähnlich wie host und port mit getaddrinfo() aufgelöst.

  • ssl_handshake_timeout ist (für eine TLS-Verbindung) die Zeit in Sekunden, die auf den Abschluss des TLS-Handshakes gewartet wird, bevor die Verbindung abgebrochen wird. 60.0 Sekunden, wenn None (Standard).

  • ssl_shutdown_timeout ist die Zeit in Sekunden, die auf den Abschluss des SSL-Shutdowns gewartet wird, bevor die Verbindung abgebrochen wird. 30.0 Sekunden, wenn None (Standard).

  • all_errors bestimmt, welche Ausnahmen ausgelöst werden, wenn eine Verbindung nicht erstellt werden kann. Standardmäßig wird nur eine einzige Exception ausgelöst: die erste Ausnahme, wenn es nur eine gibt oder alle Fehler dieselbe Nachricht haben, oder eine einzelne OSError mit kombinierten Fehlermeldungen. Wenn all_errors True ist, wird eine ExceptionGroup ausgelöst, die alle Ausnahmen enthält (auch wenn es nur eine gibt).

Geändert in Version 3.5: Unterstützung für SSL/TLS in ProactorEventLoop hinzugefügt.

Geändert in Version 3.6: Die Socket-Option socket.TCP_NODELAY wird standardmäßig für alle TCP-Verbindungen gesetzt.

Geändert in Version 3.7: Der Parameter ssl_handshake_timeout wurde hinzugefügt.

Geändert in Version 3.8: Die Parameter happy_eyeballs_delay und interleave wurden hinzugefügt.

Happy Eyeballs Algorithmus: Erfolg mit Dual-Stack-Hosts. Wenn der IPv4-Pfad und das Protokoll eines Servers funktionieren, aber der IPv6-Pfad und das Protokoll des Servers nicht funktionieren, erfährt eine Dual-Stack-Clientanwendung eine erhebliche Verbindungsverzögerung im Vergleich zu einem IPv4-only-Client. Dies ist unerwünscht, da es dazu führt, dass der Dual-Stack-Client eine schlechtere Benutzererfahrung hat. Dieses Dokument spezifiziert die Anforderungen für Algorithmen, die diese benutzerseitig sichtbare Verzögerung reduzieren, und stellt einen Algorithmus bereit.

Weitere Informationen: https://datatracker.ietf.org/doc/html/rfc6555

Geändert in Version 3.11: Der Parameter ssl_shutdown_timeout wurde hinzugefügt.

Geändert in Version 3.12: all_errors wurde hinzugefügt.

Siehe auch

Die Funktion open_connection() ist eine High-Level-Alternative API. Sie gibt ein Paar aus (StreamReader, StreamWriter) zurück, die direkt in async/await-Code verwendet werden kann.

async loop.create_datagram_endpoint(protocol_factory, local_addr=None, remote_addr=None, *, family=0, proto=0, flags=0, reuse_port=None, allow_broadcast=None, sock=None)

Erstellt eine Datagrammverbindung.

Die Socket-Familie kann entweder AF_INET, AF_INET6 oder AF_UNIX sein, abhängig von host (oder dem Argument family, falls angegeben).

Der Socket-Typ ist SOCK_DGRAM.

protocol_factory muss ein Callable sein, das eine Protokoll-Implementierung zurückgibt.

Ein Tupel aus (transport, protocol) wird bei Erfolg zurückgegeben.

Weitere Argumente

  • local_addr, falls gegeben, ist ein Tupel (local_host, local_port), das zum lokalen Binden des Sockets verwendet wird. local_host und local_port werden mit getaddrinfo() aufgelöst.

    Hinweis

    Unter Windows wird bei der Verwendung der Proactor-Ereignisschleife mit local_addr=None eine OSError mit errno.WSAEINVAL ausgelöst.

  • remote_addr, falls gegeben, ist ein Tupel (remote_host, remote_port), das zum Verbinden des Sockets mit einer Remote-Adresse verwendet wird. remote_host und remote_port werden mit getaddrinfo() aufgelöst.

  • family, proto, flags sind die optionalen Adressfamilie, das Protokoll und die Flags, die zur Auflösung von host an getaddrinfo() übergeben werden. Falls angegeben, sollten dies alles Ganzzahlen aus den entsprechenden Konstanten des socket-Moduls sein.

  • reuse_port teilt dem Kernel mit, dass dieser Endpunkt an denselben Port gebunden werden darf, an den auch andere vorhandene Endpunkte gebunden sind, vorausgesetzt, alle setzen dieses Flag bei der Erstellung. Diese Option wird unter Windows und einigen Unix-Systemen nicht unterstützt. Wenn die Konstante socket.SO_REUSEPORT nicht definiert ist, ist diese Funktionalität nicht unterstützt.

  • allow_broadcast teilt dem Kernel mit, dass dieser Endpunkt Nachrichten an die Broadcast-Adresse senden darf.

  • sock kann optional angegeben werden, um ein bereits vorhandenes, bereits verbundenes socket.socket-Objekt zu verwenden, das vom Transport genutzt wird. Wenn sock angegeben ist, sollten local_addr und remote_addr weggelassen werden (müssen None sein).

    Hinweis

    Das Argument sock überträgt das Eigentum am Socket an den erstellten Transport. Um den Socket zu schließen, rufen Sie die Methode close() des Transports auf.

Siehe die Beispiele UDP Echo-Client-Protokoll und UDP Echo-Server-Protokoll.

Geändert in Version 3.4.4: Die Parameter family, proto, flags, reuse_address, reuse_port, allow_broadcast und sock wurden hinzugefügt.

Geändert in Version 3.8: Unterstützung für Windows hinzugefügt.

Geändert in Version 3.8.1: Der Parameter reuse_address wird nicht mehr unterstützt, da die Verwendung von socket.SO_REUSEADDR ein erhebliches Sicherheitsrisiko für UDP darstellt. Das explizite Übergeben von reuse_address=True löst eine Ausnahme aus.

Wenn mehrere Prozesse mit unterschiedlichen UIDs Sockets an dieselbe UDP-Socket-Adresse mit SO_REUSEADDR binden, können eingehende Pakete zufällig auf die Sockets verteilt werden.

Auf unterstützten Plattformen kann reuse_port als Ersatz für ähnliche Funktionalität verwendet werden. Mit reuse_port wird stattdessen socket.SO_REUSEPORT verwendet, was insbesondere verhindert, dass Prozesse mit unterschiedlichen UIDs Sockets an dieselbe Socket-Adresse binden.

Geändert in Version 3.11: Der Parameter reuse_address, der seit Python 3.8.1, 3.7.6 und 3.6.10 deaktiviert war, wurde vollständig entfernt.

async loop.create_unix_connection(protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)

Erstellt eine Unix-Verbindung.

Die Socket-Familie ist AF_UNIX; der Socket-Typ ist SOCK_STREAM.

Ein Tupel aus (transport, protocol) wird bei Erfolg zurückgegeben.

path ist der Name eines Unix-Domain-Sockets und ist erforderlich, es sei denn, ein sock-Parameter ist angegeben. Abstrakte Unix-Sockets, str, bytes und Path-Pfade werden unterstützt.

Siehe die Dokumentation der Methode loop.create_connection() für Informationen zu den Argumenten dieser Methode.

Geändert in Version 3.7: Der Parameter ssl_handshake_timeout wurde hinzugefügt. Der Parameter path kann jetzt ein pfadähnliches Objekt sein.

Geändert in Version 3.11: Der Parameter ssl_shutdown_timeout wurde hinzugefügt.

Netzwerkserver erstellen

async loop.create_server(protocol_factory, host=None, port=None, *, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, keep_alive=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, start_serving=True)

Erstellt einen TCP-Server (Socket-Typ SOCK_STREAM), der auf port der Adresse host lauscht.

Gibt ein Server-Objekt zurück.

Argumente

  • protocol_factory muss ein Callable sein, das eine Protokoll-Implementierung zurückgibt.

  • Der Parameter host kann auf verschiedene Arten gesetzt werden, die bestimmen, wo der Server lauschen wird:

    • Wenn host ein String ist, wird der TCP-Server an eine einzelne Netzwerkschnittstelle gebunden, die durch host angegeben ist.

    • Wenn host eine Sequenz von Strings ist, wird der TCP-Server an alle durch die Sequenz angegebenen Netzwerkschnittstellen gebunden.

    • Wenn host ein leerer String oder None ist, werden alle Schnittstellen angenommen und eine Liste von mehreren Sockets zurückgegeben (wahrscheinlich einer für IPv4 und ein weiterer für IPv6).

  • Der Parameter port kann gesetzt werden, um anzugeben, auf welchem Port der Server lauschen soll. Wenn 0 oder None (Standard) angegeben wird, wird ein zufälliger ungenutzter Port ausgewählt (beachten Sie, dass bei Auflösung von host auf mehrere Netzwerkschnittstellen für jede Schnittstelle ein anderer zufälliger Port ausgewählt wird).

  • family kann entweder auf socket.AF_INET oder socket.AF_INET6 gesetzt werden, um den Socket zu zwingen, IPv4 oder IPv6 zu verwenden. Wenn nicht gesetzt, wird die family aus dem Hostnamen ermittelt (Standard ist AF_UNSPEC).

  • flags ist eine Bitmaske für getaddrinfo().

  • sock kann optional angegeben werden, um ein bereits vorhandenes Socket-Objekt zu verwenden. Wenn angegeben, dürfen host und port nicht angegeben werden.

    Hinweis

    Das Argument sock überträgt das Eigentum am Socket an den erstellten Server. Um den Socket zu schließen, rufen Sie die Methode close() des Servers auf.

  • backlog ist die maximale Anzahl von Warteschlangen für Verbindungen, die an listen() übergeben wird (Standard ist 100).

  • ssl kann auf eine SSLContext-Instanz gesetzt werden, um TLS über die akzeptierten Verbindungen zu aktivieren.

  • reuse_address teilt dem Kernel mit, dass ein lokaler Socket im Zustand TIME_WAIT wiederverwendet werden kann, ohne auf den natürlichen Timeout zu warten. Wenn nicht angegeben, wird unter Unix standardmäßig True gesetzt.

  • reuse_port teilt dem Kernel mit, dass dieser Endpunkt an denselben Port gebunden werden darf, an den auch andere vorhandene Endpunkte gebunden sind, vorausgesetzt, alle setzen dieses Flag bei der Erstellung. Diese Option wird unter Windows nicht unterstützt.

  • keep_alive, wenn auf True gesetzt, hält Verbindungen aktiv, indem periodisch Nachrichten gesendet werden.

Geändert in Version 3.13: Der Parameter keep_alive wurde hinzugefügt.

  • ssl_handshake_timeout ist (für einen TLS-Server) die Zeit in Sekunden, die auf den Abschluss des TLS-Handshakes gewartet wird, bevor die Verbindung abgebrochen wird. 60.0 Sekunden, wenn None (Standard).

  • ssl_shutdown_timeout ist die Zeit in Sekunden, die auf den Abschluss des SSL-Shutdowns gewartet wird, bevor die Verbindung abgebrochen wird. 30.0 Sekunden, wenn None (Standard).

  • start_serving, wenn auf True (Standard) gesetzt, bewirkt, dass der erstellte Server sofort mit der Annahme von Verbindungen beginnt. Wenn auf False gesetzt, sollte der Benutzer auf Server.start_serving() oder Server.serve_forever() warten, damit der Server mit der Annahme von Verbindungen beginnt.

Geändert in Version 3.5: Unterstützung für SSL/TLS in ProactorEventLoop hinzugefügt.

Geändert in Version 3.5.1: Der Parameter host kann eine Sequenz von Strings sein.

Geändert in Version 3.6: Die Parameter ssl_handshake_timeout und start_serving wurden hinzugefügt. Die Socket-Option socket.TCP_NODELAY wird standardmäßig für alle TCP-Verbindungen gesetzt.

Geändert in Version 3.11: Der Parameter ssl_shutdown_timeout wurde hinzugefügt.

Siehe auch

Die Funktion start_server() ist eine höherwertige alternative API, die ein Paar aus StreamReader und StreamWriter zurückgibt, die in einem async/await-Code verwendet werden können.

async loop.create_unix_server(protocol_factory, path=None, *, sock=None, backlog=100, ssl=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, start_serving=True, cleanup_socket=True)

Ähnlich wie loop.create_server(), arbeitet aber mit der AF_UNIX Socket-Familie.

path ist der Name eines Unix-Domain-Sockets und ist erforderlich, es sei denn, ein sock-Argument wird bereitgestellt. Abstrakte Unix-Sockets, str, bytes und Path-Pfade werden unterstützt.

Wenn cleanup_socket wahr ist, wird der Unix-Socket automatisch aus dem Dateisystem entfernt, wenn der Server geschlossen wird, es sei denn, der Socket wurde nach der Erstellung des Servers ersetzt.

Siehe die Dokumentation der Methode loop.create_server() für Informationen über die Argumente dieser Methode.

Geändert in Version 3.7: Die Parameter ssl_handshake_timeout und start_serving wurden hinzugefügt. Der Parameter path kann jetzt ein Path-Objekt sein.

Geändert in Version 3.11: Der Parameter ssl_shutdown_timeout wurde hinzugefügt.

Geändert in Version 3.13: Der Parameter cleanup_socket wurde hinzugefügt.

async loop.connect_accepted_socket(protocol_factory, sock, *, ssl=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)

Wickelt eine bereits akzeptierte Verbindung in ein Transport-/Protokollpaar ein.

Diese Methode kann von Servern verwendet werden, die Verbindungen außerhalb von asyncio akzeptieren, diese aber mit asyncio verarbeiten.

Parameter

  • protocol_factory muss ein Callable sein, das eine Protokoll-Implementierung zurückgibt.

  • sock ist ein bereits vorhandenes Socket-Objekt, das von socket.accept zurückgegeben wird.

    Hinweis

    Das Argument sock überträgt das Eigentum am Socket an den erstellten Transport. Um den Socket zu schließen, rufen Sie die Methode close() des Transports auf.

  • ssl kann auf einen SSLContext gesetzt werden, um SSL über die akzeptierten Verbindungen zu aktivieren.

  • ssl_handshake_timeout ist (für eine SSL-Verbindung) die Zeit in Sekunden, die auf den Abschluss des SSL-Handshakes gewartet wird, bevor die Verbindung abgebrochen wird. 60.0 Sekunden, wenn None (Standard).

  • ssl_shutdown_timeout ist die Zeit in Sekunden, die auf den Abschluss des SSL-Shutdowns gewartet wird, bevor die Verbindung abgebrochen wird. 30.0 Sekunden, wenn None (Standard).

Gibt ein (transport, protocol)-Paar zurück.

Hinzugefügt in Version 3.5.3.

Geändert in Version 3.7: Der Parameter ssl_handshake_timeout wurde hinzugefügt.

Geändert in Version 3.11: Der Parameter ssl_shutdown_timeout wurde hinzugefügt.

Dateiübertragung

async loop.sendfile(transport, file, offset=0, count=None, *, fallback=True)

Sendet eine Datei über einen transport. Gibt die Gesamtzahl der gesendeten Bytes zurück.

Die Methode verwendet das Hochleistungs- os.sendfile(), falls verfügbar.

file muss ein reguläres Dateiobjekt sein, das im Binärmodus geöffnet wurde.

offset gibt an, ab welcher Stelle die Datei gelesen werden soll. Wenn angegeben, ist count die Gesamtzahl der zu übertragenden Bytes, anstatt die Datei bis zum EOF zu senden. Die Dateiposition wird immer aktualisiert, auch wenn diese Methode einen Fehler auslöst, und file.tell() kann verwendet werden, um die tatsächlich gesendeten Bytes zu ermitteln.

fallback auf True gesetzt, bewirkt, dass asyncio die Datei manuell liest und sendet, wenn die Plattform den sendfile-Systemaufruf nicht unterstützt (z. B. Windows oder SSL-Socket unter Unix).

Löst SendfileNotAvailableError aus, wenn das System den sendfile-Syscall nicht unterstützt und fallback False ist.

Hinzugefügt in Version 3.7.

TLS-Upgrade

async loop.start_tls(transport, protocol, sslcontext, *, server_side=False, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)

Ein vorhandener Transport-basierter Verbindung auf TLS upgraden.

Erstellt eine TLS-Coder/Decoder-Instanz und fügt sie zwischen den transport und das protocol ein. Der Coder/Decoder implementiert sowohl das transport-seitige Protokoll als auch den protokollseitigen Transport.

Gibt die erstellte Zwei-Interface-Instanz zurück. Nach dem await muss das protocol die ursprüngliche transport nicht mehr verwenden und nur noch mit dem zurückgegebenen Objekt kommunizieren, da der Coder protokollseitige Daten zwischenspeichert und sporadisch zusätzliche TLS-Sitzungspakete mit transport austauscht.

In einigen Situationen (z. B. wenn der übergebene Transport bereits geschlossen wird) kann dies None zurückgeben.

Parameter

  • transport und protocol-Instanzen, die Methoden wie create_server() und create_connection() zurückgeben.

  • sslcontext: eine konfigurierte Instanz von SSLContext.

  • server_side setzen Sie True, wenn eine serverseitige Verbindung hochgestuft wird (wie die von create_server() erstellte).

  • server_hostname: legt den Hostnamen fest oder überschreibt ihn, gegen den das Zertifikat des Zielservers abgeglichen werden soll.

  • ssl_handshake_timeout ist (für eine TLS-Verbindung) die Zeit in Sekunden, die auf den Abschluss des TLS-Handshakes gewartet wird, bevor die Verbindung abgebrochen wird. 60.0 Sekunden, wenn None (Standard).

  • ssl_shutdown_timeout ist die Zeit in Sekunden, die auf den Abschluss des SSL-Shutdowns gewartet wird, bevor die Verbindung abgebrochen wird. 30.0 Sekunden, wenn None (Standard).

Hinzugefügt in Version 3.7.

Geändert in Version 3.11: Der Parameter ssl_shutdown_timeout wurde hinzugefügt.

Überwachung von Dateideskriptoren

loop.add_reader(fd, callback, *args)

Beginnt mit der Überwachung des Dateideskriptors fd auf Leseverfügbarkeit und ruft callback mit den angegebenen Argumenten auf, sobald fd zum Lesen verfügbar ist.

Jeder bereits für fd registrierte Callback wird abgebrochen und durch callback ersetzt.

loop.remove_reader(fd)

Beendet die Überwachung des Dateideskriptors fd auf Leseverfügbarkeit. Gibt True zurück, wenn fd zuvor für das Lesen überwacht wurde.

loop.add_writer(fd, callback, *args)

Beginnt mit der Überwachung des Dateideskriptors fd auf Schreibverfügbarkeit und ruft callback mit den angegebenen Argumenten auf, sobald fd zum Schreiben verfügbar ist.

Jeder bereits für fd registrierte Callback wird abgebrochen und durch callback ersetzt.

Verwenden Sie functools.partial() zum Übergeben von Schlüsselwortargumenten an callback.

loop.remove_writer(fd)

Beendet die Überwachung des Dateideskriptors fd auf Schreibverfügbarkeit. Gibt True zurück, wenn fd zuvor für das Schreiben überwacht wurde.

Siehe auch den Abschnitt Plattformunterstützung für einige Einschränkungen dieser Methoden.

Arbeiten mit Socket-Objekten direkt

Im Allgemeinen sind Protokollimplementierungen, die transportbasierte APIs wie loop.create_connection() und loop.create_server() verwenden, schneller als Implementierungen, die direkt mit Sockets arbeiten. Es gibt jedoch einige Anwendungsfälle, bei denen die Leistung nicht kritisch ist und die Arbeit mit socket-Objekten direkt bequemer ist.

async loop.sock_recv(sock, nbytes)

Empfängt bis zu nbytes von sock. Asynchrone Version von socket.recv().

Gibt die empfangenen Daten als Bytes-Objekt zurück.

sock muss ein nicht-blockierender Socket sein.

Geändert in Version 3.7: Obwohl diese Methode immer als Koroutinenmethode dokumentiert war, gaben Versionen vor Python 3.7 ein Future zurück. Seit Python 3.7 ist dies eine async def-Methode.

async loop.sock_recv_into(sock, buf)

Empfängt Daten von sock in den buf-Puffer. Modelliert nach der blockierenden Methode socket.recv_into().

Gibt die Anzahl der in den Puffer geschriebenen Bytes zurück.

sock muss ein nicht-blockierender Socket sein.

Hinzugefügt in Version 3.7.

async loop.sock_recvfrom(sock, bufsize)

Empfängt ein Datagramm von bis zu bufsize von sock. Asynchrone Version von socket.recvfrom().

Gibt ein Tupel aus (empfangene Daten, entfernte Adresse) zurück.

sock muss ein nicht-blockierender Socket sein.

Hinzugefügt in Version 3.11.

async loop.sock_recvfrom_into(sock, buf, nbytes=0)

Empfängt ein Datagramm von bis zu nbytes von sock in buf. Asynchrone Version von socket.recvfrom_into().

Gibt ein Tupel aus (Anzahl der empfangenen Bytes, entfernte Adresse) zurück.

sock muss ein nicht-blockierender Socket sein.

Hinzugefügt in Version 3.11.

async loop.sock_sendall(sock, data)

Sendet data an den sock-Socket. Asynchrone Version von socket.sendall().

Diese Methode sendet kontinuierlich an den Socket, bis entweder alle Daten in data gesendet wurden oder ein Fehler auftritt. Bei Erfolg wird None zurückgegeben. Bei einem Fehler wird eine Ausnahme ausgelöst. Außerdem gibt es keine Möglichkeit zu ermitteln, wie viele Daten, falls überhaupt, vom empfangenden Ende der Verbindung erfolgreich verarbeitet wurden.

sock muss ein nicht-blockierender Socket sein.

Geändert in Version 3.7: Obwohl die Methode immer als Koroutinenmethode dokumentiert war, gaben Versionen vor Python 3.7 ein Future zurück. Seit Python 3.7 ist dies eine async def-Methode.

async loop.sock_sendto(sock, data, address)

Sendet ein Datagramm von sock an address. Asynchrone Version von socket.sendto().

Gibt die Anzahl der gesendeten Bytes zurück.

sock muss ein nicht-blockierender Socket sein.

Hinzugefügt in Version 3.11.

async loop.sock_connect(sock, address)

Verbindet sock mit einem entfernten Socket unter address.

Asynchrone Version von socket.connect().

sock muss ein nicht-blockierender Socket sein.

Geändert in Version 3.5.2: address muss nicht mehr aufgelöst werden. sock_connect versucht zu prüfen, ob address bereits aufgelöst ist, indem socket.inet_pton() aufgerufen wird. Wenn nicht, wird loop.getaddrinfo() verwendet, um address aufzulösen.

async loop.sock_accept(sock)

Akzeptiert eine Verbindung. Modelliert nach der blockierenden Methode socket.accept().

Der Socket muss an eine Adresse gebunden und für Verbindungen offen sein. Der Rückgabewert ist ein Paar (conn, address), wobei conn ein neues Socket-Objekt ist, das zum Senden und Empfangen von Daten über die Verbindung verwendet werden kann, und address die an den Socket am anderen Ende der Verbindung gebundene Adresse ist.

sock muss ein nicht-blockierender Socket sein.

Geändert in Version 3.7: Obwohl die Methode immer als Koroutinenmethode dokumentiert war, gaben Versionen vor Python 3.7 ein Future zurück. Seit Python 3.7 ist dies eine async def-Methode.

async loop.sock_sendfile(sock, file, offset=0, count=None, *, fallback=True)

Sendet eine Datei mit dem Hochleistungs- os.sendfile, falls möglich. Gibt die Gesamtzahl der gesendeten Bytes zurück.

Asynchrone Version von socket.sendfile().

sock muss ein nicht-blockierender socket.SOCK_STREAM socket sein.

file muss ein reguläres Dateiobjekt sein, das im Binärmodus geöffnet ist.

offset gibt an, ab welcher Stelle die Datei gelesen werden soll. Wenn angegeben, ist count die Gesamtzahl der zu übertragenden Bytes, anstatt die Datei bis zum EOF zu senden. Die Dateiposition wird immer aktualisiert, auch wenn diese Methode einen Fehler auslöst, und file.tell() kann verwendet werden, um die tatsächlich gesendeten Bytes zu ermitteln.

fallback bewirkt, wenn es auf True gesetzt ist, dass asyncio die Datei manuell liest und sendet, wenn die Plattform den sendfile-Systemaufruf nicht unterstützt (z. B. Windows oder SSL-Socket unter Unix).

Löst SendfileNotAvailableError aus, wenn das System den sendfile-Systemaufruf nicht unterstützt und fallback False ist.

sock muss ein nicht-blockierender Socket sein.

Hinzugefügt in Version 3.7.

DNS

async loop.getaddrinfo(host, port, *, family=0, type=0, proto=0, flags=0)

Asynchrone Version von socket.getaddrinfo().

async loop.getnameinfo(sockaddr, flags=0)

Asynchrone Version von socket.getnameinfo().

Hinweis

Sowohl getaddrinfo als auch getnameinfo nutzen intern ihre synchronen Versionen über den Standard-Threadpool-Executor der Schleife. Wenn dieser Executor gesättigt ist, können diese Methoden Verzögerungen erfahren, die höherstufige Netzwerkbibliotheken als erhöhte Timeouts melden können. Um dies zu mildern, sollten Sie erwägen, einen benutzerdefinierten Executor für andere Benutzertasks zu verwenden oder einen Standard-Executor mit einer größeren Anzahl von Arbeitern einzurichten.

Geändert in Version 3.7: Sowohl die Methoden getaddrinfo als auch getnameinfo gaben immer eine Koroutine zurück, aber vor Python 3.7 gaben sie tatsächlich asyncio.Future-Objekte zurück. Ab Python 3.7 sind beide Methoden Koroutinen.

Arbeiten mit Pipes

async loop.connect_read_pipe(protocol_factory, pipe)

Registriert das Leseende von pipe in der Event-Schleife.

protocol_factory muss ein Callable sein, das eine asyncio-Protokoll-Implementierung zurückgibt.

pipe ist ein dateiähnliches Objekt.

Gibt das Paar (transport, protocol) zurück, wobei transport die ReadTransport-Schnittstelle unterstützt und protocol ein Objekt ist, das von protocol_factory instanziiert wurde.

Mit der SelectorEventLoop Ereignisschleife wird die Pipe in den nicht-blockierenden Modus versetzt.

async loop.connect_write_pipe(protocol_factory, pipe)

Registriert das Schreibende von pipe in der Ereignisschleife.

protocol_factory muss ein Callable sein, das eine asyncio-Protokoll-Implementierung zurückgibt.

pipe ist ein dateiähnliches Objekt.

Gibt ein Paar (transport, protocol) zurück, wobei transport die WriteTransport Schnittstelle unterstützt und protocol ein von protocol_factory instanziiertes Objekt ist.

Mit der SelectorEventLoop Ereignisschleife wird die Pipe in den nicht-blockierenden Modus versetzt.

Hinweis

SelectorEventLoop unterstützt die obigen Methoden unter Windows nicht. Verwenden Sie stattdessen ProactorEventLoop für Windows.

Siehe auch

Die Methoden loop.subprocess_exec() und loop.subprocess_shell().

Unix-Signale

loop.add_signal_handler(signum, callback, *args)

Setzt callback als Handler für das signum Signal.

Der Callback wird von loop aufgerufen, zusammen mit anderen wartenden Callbacks und ausführbaren Coroutinen dieser Ereignisschleife. Im Gegensatz zu Signal-Handlern, die über signal.signal() registriert werden, darf ein mit dieser Funktion registrierter Callback mit der Ereignisschleife interagieren.

Löst ValueError aus, wenn die Signalnummer ungültig oder nicht abfangbar ist. Löst RuntimeError aus, wenn ein Problem beim Einrichten des Handlers auftritt.

Verwenden Sie functools.partial() zum Übergeben von Schlüsselwortargumenten an callback.

Wie signal.signal() muss diese Funktion im Hauptthread aufgerufen werden.

loop.remove_signal_handler(sig)

Entfernt den Handler für das sig Signal.

Gibt True zurück, wenn der Signal-Handler entfernt wurde, oder False, wenn kein Handler für das gegebene Signal gesetzt war.

Siehe auch

Das Modul signal.

Ausführung von Code in Thread- oder Prozesspools

awaitable loop.run_in_executor(executor, func, *args)

Veranlasst, dass func im angegebenen Executor aufgerufen wird.

Das Argument executor sollte eine Instanz von concurrent.futures.Executor sein. Der Standard-Executor wird verwendet, wenn executor None ist. Der Standard-Executor kann durch loop.set_default_executor() gesetzt werden, andernfalls wird ein concurrent.futures.ThreadPoolExecutor lazy-initialisiert und bei Bedarf von run_in_executor() verwendet.

Beispiel

import asyncio
import concurrent.futures

def blocking_io():
    # File operations (such as logging) can block the
    # event loop: run them in a thread pool.
    with open('/dev/urandom', 'rb') as f:
        return f.read(100)

def cpu_bound():
    # CPU-bound operations will block the event loop:
    # in general it is preferable to run them in a
    # process pool.
    return sum(i * i for i in range(10 ** 7))

async def main():
    loop = asyncio.get_running_loop()

    ## Options:

    # 1. Run in the default loop's executor:
    result = await loop.run_in_executor(
        None, blocking_io)
    print('default thread pool', result)

    # 2. Run in a custom thread pool:
    with concurrent.futures.ThreadPoolExecutor() as pool:
        result = await loop.run_in_executor(
            pool, blocking_io)
        print('custom thread pool', result)

    # 3. Run in a custom process pool:
    with concurrent.futures.ProcessPoolExecutor() as pool:
        result = await loop.run_in_executor(
            pool, cpu_bound)
        print('custom process pool', result)

    # 4. Run in a custom interpreter pool:
    with concurrent.futures.InterpreterPoolExecutor() as pool:
        result = await loop.run_in_executor(
            pool, cpu_bound)
        print('custom interpreter pool', result)

if __name__ == '__main__':
    asyncio.run(main())

Beachten Sie, dass die Einstiegspunkt-Guard (if __name__ == '__main__') für Option 3 aufgrund der Besonderheiten von multiprocessing erforderlich ist, das von ProcessPoolExecutor verwendet wird. Siehe Sicheres Importieren des Hauptmoduls.

Diese Methode gibt ein asyncio.Future Objekt zurück.

Verwenden Sie functools.partial() um Schlüsselwortargumente an func zu übergeben.

Geändert in Version 3.5.3: loop.run_in_executor() konfiguriert die max_workers des von ihm erstellten Thread-Pool-Executors nicht mehr, sondern überlässt es dem Thread-Pool-Executor (ThreadPoolExecutor), den Standardwert festzulegen.

loop.set_default_executor(executor)

Setzt executor als Standard-Executor, der von run_in_executor() verwendet wird. executor muss eine Instanz von ThreadPoolExecutor sein, was InterpreterPoolExecutor einschließt.

Geändert in Version 3.11: executor muss eine Instanz von ThreadPoolExecutor sein.

API zur Fehlerbehandlung

Ermöglicht die Anpassung der Behandlung von Ausnahmen in der Ereignisschleife.

loop.set_exception_handler(handler)

Setzt handler als neuen Ausnahmekoordinator der Ereignisschleife.

Wenn handler None ist, wird der Standard-Ausnahmekoordinator gesetzt. Andernfalls muss handler ein aufrufbares Objekt sein, dessen Signatur mit (loop, context) übereinstimmt, wobei loop ein Verweis auf die aktive Ereignisschleife ist und context ein dict-Objekt ist, das die Details der Ausnahme enthält (siehe Dokumentation zu call_exception_handler() für Details zum Kontext).

Wenn der Handler im Auftrag eines Task oder Handle aufgerufen wird, wird er im contextvars.Context dieses Tasks oder Callback-Handles ausgeführt.

Geändert in Version 3.12: Der Handler kann im Context des Tasks oder Handles, aus dem die Ausnahme stammt, aufgerufen werden.

loop.get_exception_handler()

Gibt den aktuellen Ausnahmekoordinator zurück oder None, wenn kein benutzerdefinierter Ausnahmekoordinator gesetzt wurde.

Hinzugefügt in Version 3.5.2.

loop.default_exception_handler(context)

Standard-Ausnahmekoordinator.

Dies wird aufgerufen, wenn eine Ausnahme auftritt und kein Ausnahmekoordinator gesetzt ist. Dies kann von einem benutzerdefinierten Ausnahmekoordinator aufgerufen werden, der das Standardverhalten des Koordinators beibehalten möchte.

Der Parameter context hat die gleiche Bedeutung wie in call_exception_handler().

loop.call_exception_handler(context)

Ruft den aktuellen Ausnahmekoordinator der Ereignisschleife auf.

context ist ein dict-Objekt, das die folgenden Schlüssel enthält (in zukünftigen Python-Versionen können weitere Schlüssel hinzugefügt werden)

  • ‘message’: Fehlermeldung;

  • ‘exception’ (optional): Ausnahmeobjekt;

  • ‘future’ (optional): asyncio.Future Instanz;

  • ‘task’ (optional): asyncio.Task Instanz;

  • ‘handle’ (optional): asyncio.Handle Instanz;

  • ‘protocol’ (optional): Protokoll Instanz;

  • ‘transport’ (optional): Transport Instanz;

  • ‘socket’ (optional): socket.socket Instanz;

  • ‘source_traceback’ (optional): Traceback der Quelle;

  • ‘handle_traceback’ (optional): Traceback des Handles;

  • ‘asyncgen’ (optional): Asynchroner Generator, der die

    Ausnahme verursacht hat.

Hinweis

Diese Methode sollte in abgeleiteten Ereignisschleifen nicht überschrieben werden. Verwenden Sie für benutzerdefinierte Ausnahmebehandlung die Methode set_exception_handler().

Aktivieren des Debug-Modus

loop.get_debug()

Ruft den Debug-Modus (bool) der Ereignisschleife ab.

Der Standardwert ist True, wenn die Umgebungsvariable PYTHONASYNCIODEBUG auf eine nicht-leere Zeichenkette gesetzt ist, andernfalls False.

loop.set_debug(enabled: bool)

Setzt den Debug-Modus der Ereignisschleife.

Geändert in Version 3.7: Der neue Python-Entwicklermodus kann auch verwendet werden, um den Debug-Modus zu aktivieren.

loop.slow_callback_duration

Dieses Attribut kann verwendet werden, um die minimale Ausführungsdauer in Sekunden festzulegen, die als "langsam" gilt. Wenn der Debug-Modus aktiviert ist, werden "langsame" Callbacks protokolliert.

Standardwert ist 100 Millisekunden.

Siehe auch

Der Debug-Modus von asyncio.

Ausführung von Subprozessen

Die in diesem Unterabschnitt beschriebenen Methoden sind Low-Level. In normalem Async/Await-Code sollten stattdessen die High-Level-Komfortfunktionen asyncio.create_subprocess_shell() und asyncio.create_subprocess_exec() verwendet werden.

Hinweis

Unter Windows unterstützt die Standard-Ereignisschleife ProactorEventLoop Subprozesse, während SelectorEventLoop dies nicht tut. Siehe Unterstützung für Subprozesse unter Windows für Details.

async loop.subprocess_exec(protocol_factory, *args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)

Erstellt einen Subprozess aus einem oder mehreren Zeichenkettenargumenten, die durch args angegeben werden.

args muss eine Liste von Zeichenketten sein, dargestellt durch

Die erste Zeichenkette gibt das Programm-Executable an, die restlichen Zeichenketten die Argumente. Zusammen bilden die Zeichenkettenargumente die argv des Programms.

Dies ähnelt der Standardbibliotheksklasse subprocess.Popen, aufgerufen mit shell=False und der Zeichenkettenliste als erstem Argument; wobei Popen ein einzelnes Argument erwartet, das eine Liste von Zeichenketten ist, nimmt subprocess_exec mehrere Zeichenkettenargumente.

protocol_factory muss ein aufrufbares Objekt sein, das eine Unterklasse der Klasse asyncio.SubprocessProtocol zurückgibt.

Andere Parameter

  • stdin kann eines der folgenden sein:

    • ein dateiähnliches Objekt

    • ein bestehender Dateideskriptor (eine positive Ganzzahl), z. B. erzeugt mit os.pipe()

    • die Konstante subprocess.PIPE (Standard), die eine neue Pipe erstellt und sie verbindet,

    • der Wert None, der dazu führt, dass der Subprozess den Dateideskriptor von diesem Prozess erbt

    • die Konstante subprocess.DEVNULL, die angibt, dass die spezielle Datei os.devnull verwendet wird

  • stdout kann eines der folgenden sein:

    • ein dateiähnliches Objekt

    • die Konstante subprocess.PIPE (Standard), die eine neue Pipe erstellt und sie verbindet,

    • der Wert None, der dazu führt, dass der Subprozess den Dateideskriptor von diesem Prozess erbt

    • die Konstante subprocess.DEVNULL, die angibt, dass die spezielle Datei os.devnull verwendet wird

  • stderr kann eines der folgenden sein:

    • ein dateiähnliches Objekt

    • die Konstante subprocess.PIPE (Standard), die eine neue Pipe erstellt und sie verbindet,

    • der Wert None, der dazu führt, dass der Subprozess den Dateideskriptor von diesem Prozess erbt

    • die Konstante subprocess.DEVNULL, die angibt, dass die spezielle Datei os.devnull verwendet wird

    • die Konstante subprocess.STDOUT, die den Standardfehlerstrom mit dem Standardausgabestrom des Prozesses verbindet

  • Alle anderen Schlüsselwortargumente werden ohne Interpretation an subprocess.Popen übergeben, mit Ausnahme von bufsize, universal_newlines, shell, text, encoding und errors, die überhaupt nicht angegeben werden sollten.

    Die asyncio Subprozess-API unterstützt nicht das Dekodieren von Streams als Text. bytes.decode() kann verwendet werden, um die von den Streams zurückgegebenen Bytes in Text umzuwandeln.

Wenn ein dateiähnliches Objekt, das als stdin, stdout oder stderr übergeben wird, eine Pipe repräsentiert, dann sollte die andere Seite dieser Pipe mit connect_write_pipe() oder connect_read_pipe() für die Verwendung mit der Ereignisschleife registriert werden.

Siehe den Konstruktor der Klasse subprocess.Popen für Dokumentation zu anderen Argumenten.

Gibt ein Paar von (transport, protocol) zurück, wobei transport der Basisklasse asyncio.SubprocessTransport entspricht und protocol ein von protocol_factory instanziiertes Objekt ist.

async loop.subprocess_shell(protocol_factory, cmd, *, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)

Erstellt einen Subprozess aus cmd, bei dem es sich um eine str oder eine bytes Zeichenkette handeln kann, die auf die Dateisystemkodierung kodiert ist, unter Verwendung der "Shell"-Syntax der Plattform.

Dies ähnelt der Standardbibliotheksklasse subprocess.Popen, aufgerufen mit shell=True.

protocol_factory muss ein aufrufbares Objekt sein, das eine Unterklasse der Klasse SubprocessProtocol zurückgibt.

Siehe subprocess_exec() für weitere Details zu den übrigen Argumenten.

Gibt ein Paar von (transport, protocol) zurück, wobei transport der Klasse SubprocessTransport entspricht und protocol ein von protocol_factory instanziiertes Objekt ist.

Hinweis

Es liegt in der Verantwortung der Anwendung, sicherzustellen, dass alle Leerzeichen und Sonderzeichen ordnungsgemäß maskiert werden, um Shell-Injection-Schwachstellen zu vermeiden. Die Funktion shlex.quote() kann verwendet werden, um Leerzeichen und Sonderzeichen in Zeichenketten, die zur Erstellung von Shell-Befehlen verwendet werden sollen, korrekt zu maskieren.

Callback-Handles

class asyncio.Handle

Ein Callback-Wrapper-Objekt, das von loop.call_soon(), loop.call_soon_threadsafe() zurückgegeben wird.

get_context()

Gibt das dem Handle zugeordnete contextvars.Context Objekt zurück.

Hinzugefügt in Version 3.12.

cancel()

Bricht den Callback ab. Wenn der Callback bereits abgebrochen oder ausgeführt wurde, hat diese Methode keine Auswirkung.

cancelled()

Gibt True zurück, wenn der Callback abgebrochen wurde.

Hinzugefügt in Version 3.7.

class asyncio.TimerHandle

Ein Callback-Wrapper-Objekt, das von loop.call_later() und loop.call_at() zurückgegeben wird.

Diese Klasse ist eine Unterklasse von Handle.

when()

Gibt die geplante Callback-Zeit als float Sekunden zurück.

Die Zeit ist ein absoluter Zeitstempel, der dieselbe Zeitreferenz wie loop.time() verwendet.

Hinzugefügt in Version 3.7.

Server-Objekte

Server-Objekte werden von den Funktionen loop.create_server(), loop.create_unix_server(), start_server() und start_unix_server() erstellt.

Instanziieren Sie die Klasse Server nicht direkt.

class asyncio.Server

Server-Objekte sind asynchrone Kontextmanager. Wenn sie in einer async with-Anweisung verwendet werden, ist garantiert, dass das Server-Objekt geschlossen wird und keine neuen Verbindungen akzeptiert, wenn die async with-Anweisung abgeschlossen ist

srv = await loop.create_server(...)

async with srv:
    # some code

# At this point, srv is closed and no longer accepts new connections.

Geändert in Version 3.7: Server-Objekt ist seit Python 3.7 ein asynchroner Kontextmanager.

Geändert in Version 3.11: Diese Klasse wurde in Python 3.9.11, 3.10.3 und 3.11 öffentlich als asyncio.Server exponiert.

close()

Beenden des Dienstes: Schließen der Listening-Sockets und Setzen des sockets-Attributs auf None.

Die Sockets, die bestehende eingehende Client-Verbindungen repräsentieren, bleiben geöffnet.

Der Server wird asynchron geschlossen; verwenden Sie die wait_closed() Coroutine, um zu warten, bis der Server geschlossen ist (und keine Verbindungen mehr aktiv sind).

close_clients()

Schließen Sie alle bestehenden eingehenden Client-Verbindungen.

Ruft close() auf allen zugehörigen Transports auf.

Vor dem Schließen des Servers sollte close() vor close_clients() aufgerufen werden, um Wettlaufsituationen mit neu verbundenen Clients zu vermeiden.

Hinzugefügt in Version 3.13.

abort_clients()

Schließen Sie alle bestehenden eingehenden Client-Verbindungen sofort ab, ohne auf den Abschluss ausstehender Operationen zu warten.

Ruft abort() auf allen zugehörigen Transports auf.

Vor dem Schließen des Servers sollte close() vor abort_clients() aufgerufen werden, um Wettlaufsituationen mit neu verbundenen Clients zu vermeiden.

Hinzugefügt in Version 3.13.

get_loop()

Gibt die dem Server-Objekt zugeordnete Ereignisschleife zurück.

Hinzugefügt in Version 3.7.

async start_serving()

Beginnen Sie mit dem Akzeptieren von Verbindungen.

Diese Methode ist idempotent, kann also aufgerufen werden, wenn der Server bereits bedient.

Der Schlüsselwortparameter _start_serving_ für loop.create_server() und asyncio.start_server() ermöglicht die Erstellung eines Server-Objekts, das anfangs keine Verbindungen akzeptiert. In diesem Fall kann Server.start_serving() oder Server.serve_forever() verwendet werden, um den Server mit dem Akzeptieren von Verbindungen zu beginnen.

Hinzugefügt in Version 3.7.

async serve_forever()

Beginnen Sie mit dem Akzeptieren von Verbindungen, bis die Coroutine abgebrochen wird. Ein Abbruch der serve_forever Aufgabe führt zum Schließen des Servers.

Diese Methode kann aufgerufen werden, wenn der Server bereits Verbindungen akzeptiert. Pro Server-Objekt kann nur eine serve_forever Aufgabe existieren.

Beispiel

async def client_connected(reader, writer):
    # Communicate with the client with
    # reader/writer streams.  For example:
    await reader.readline()

async def main(host, port):
    srv = await asyncio.start_server(
        client_connected, host, port)
    await srv.serve_forever()

asyncio.run(main('127.0.0.1', 0))

Hinzugefügt in Version 3.7.

is_serving()

Gibt True zurück, wenn der Server neue Verbindungen akzeptiert.

Hinzugefügt in Version 3.7.

async wait_closed()

Warten Sie, bis die Methode close() abgeschlossen ist und alle aktiven Verbindungen beendet sind.

sockets

Liste von Socket-ähnlichen Objekten, asyncio.trsock.TransportSocket, auf denen der Server lauscht.

Geändert in Version 3.7: Vor Python 3.7 gab Server.sockets eine interne Liste von Server-Sockets direkt zurück. In 3.7 wird eine Kopie dieser Liste zurückgegeben.

Implementierungen der Ereignisschleife

asyncio wird mit zwei verschiedenen Implementierungen der Ereignisschleife geliefert: SelectorEventLoop und ProactorEventLoop.

Standardmäßig ist asyncio so konfiguriert, dass es EventLoop verwendet.

class asyncio.SelectorEventLoop

Eine Unterklasse von AbstractEventLoop, die auf dem Modul selectors basiert.

Verwendet den effizientesten für die gegebene Plattform verfügbaren Selektor. Es ist auch möglich, die genaue zu verwendende Selektorimplementierung manuell zu konfigurieren.

import asyncio
import selectors

async def main():
   ...

loop_factory = lambda: asyncio.SelectorEventLoop(selectors.SelectSelector())
asyncio.run(main(), loop_factory=loop_factory)

Verfügbarkeit: Unix, Windows.

class asyncio.ProactorEventLoop

Eine Unterklasse von AbstractEventLoop für Windows, die "I/O Completion Ports" (IOCP) verwendet.

Verfügbarkeit: Windows.

class asyncio.EventLoop

Ein Alias für die für die gegebene Plattform effizienteste verfügbare Unterklasse von AbstractEventLoop.

Es ist ein Alias für SelectorEventLoop unter Unix und ProactorEventLoop unter Windows.

Hinzugefügt in Version 3.13.

class asyncio.AbstractEventLoop

Abstrakte Basisklasse für asyncio-konforme Ereignisschleifen.

Der Abschnitt Event Loop-Methoden listet alle Methoden auf, die eine alternative Implementierung von AbstractEventLoop definieren sollte.

Beispiele

Beachten Sie, dass alle Beispiele in diesem Abschnitt **absichtlich** zeigen, wie die Low-Level-Ereignisschleifen-APIs wie loop.run_forever() und loop.call_soon() verwendet werden. Moderne asyncio-Anwendungen müssen selten auf diese Weise geschrieben werden; erwägen Sie die Verwendung der High-Level-Funktionen wie asyncio.run().

Hallo Welt mit call_soon()

Ein Beispiel, das die Methode loop.call_soon() verwendet, um einen Callback zu planen. Der Callback zeigt "Hello World" an und stoppt dann die Ereignisschleife.

import asyncio

def hello_world(loop):
    """A callback to print 'Hello World' and stop the event loop"""
    print('Hello World')
    loop.stop()

loop = asyncio.new_event_loop()

# Schedule a call to hello_world()
loop.call_soon(hello_world, loop)

# Blocking call interrupted by loop.stop()
try:
    loop.run_forever()
finally:
    loop.close()

Siehe auch

Ein ähnliches Hallo Welt-Beispiel, das mit einer Coroutine und der Funktion run() erstellt wurde.

Zeige das aktuelle Datum mit call_later()

Ein Beispiel für einen Callback, der jede Sekunde das aktuelle Datum anzeigt. Der Callback verwendet die Methode loop.call_later(), um sich nach 5 Sekunden neu zu planen und stoppt dann die Ereignisschleife.

import asyncio
import datetime

def display_date(end_time, loop):
    print(datetime.datetime.now())
    if (loop.time() + 1.0) < end_time:
        loop.call_later(1, display_date, end_time, loop)
    else:
        loop.stop()

loop = asyncio.new_event_loop()

# Schedule the first call to display_date()
end_time = loop.time() + 5.0
loop.call_soon(display_date, end_time, loop)

# Blocking call interrupted by loop.stop()
try:
    loop.run_forever()
finally:
    loop.close()

Siehe auch

Ein ähnliches aktuelles Datum-Beispiel, das mit einer Coroutine und der Funktion run() erstellt wurde.

Überwachen eines Dateideskriptors auf Lesereignisse

Warten, bis ein Dateideskriptor Daten empfangen hat, mithilfe der Methode loop.add_reader(), und dann die Ereignisschleife schließen.

import asyncio
from socket import socketpair

# Create a pair of connected file descriptors
rsock, wsock = socketpair()

loop = asyncio.new_event_loop()

def reader():
    data = rsock.recv(100)
    print("Received:", data.decode())

    # We are done: unregister the file descriptor
    loop.remove_reader(rsock)

    # Stop the event loop
    loop.stop()

# Register the file descriptor for read event
loop.add_reader(rsock, reader)

# Simulate the reception of data from the network
loop.call_soon(wsock.send, 'abc'.encode())

try:
    # Run the event loop
    loop.run_forever()
finally:
    # We are done. Close sockets and the event loop.
    rsock.close()
    wsock.close()
    loop.close()

Siehe auch

Setzen von Signal-Handlern für SIGINT und SIGTERM

(Dieses signals-Beispiel funktioniert nur unter Unix.)

Registrieren von Handlern für die Signale SIGINT und SIGTERM mit der Methode loop.add_signal_handler().

import asyncio
import functools
import os
import signal

def ask_exit(signame, loop):
    print("got signal %s: exit" % signame)
    loop.stop()

async def main():
    loop = asyncio.get_running_loop()

    for signame in {'SIGINT', 'SIGTERM'}:
        loop.add_signal_handler(
            getattr(signal, signame),
            functools.partial(ask_exit, signame, loop))

    await asyncio.sleep(3600)

print("Event loop running for 1 hour, press Ctrl+C to interrupt.")
print(f"pid {os.getpid()}: send SIGINT or SIGTERM to exit.")

asyncio.run(main())