Runner¶
Quellcode: Lib/asyncio/runners.py
Dieser Abschnitt beschreibt High-Level-asyncio-Primitiven zur Ausführung von asyncio-Code.
Sie basieren auf einer Ereignisschleife mit dem Ziel, die Verwendung von asynchronem Code für häufige, weit verbreitete Szenarien zu vereinfachen.
Ein asyncio-Programm ausführen¶
- asyncio.run(coro, *, debug=None, loop_factory=None)¶
Führt coro in einer asyncio-Ereignisschleife aus und gibt das Ergebnis zurück.
Das Argument kann jedes awaitable-Objekt sein.
Diese Funktion führt das awaitable aus und kümmert sich um die Verwaltung der asyncio-Ereignisschleife, die Finalisierung asynchroner Generatoren und das Schließen des Executors.
Diese Funktion kann nicht aufgerufen werden, wenn bereits eine andere asyncio-Ereignisschleife im selben Thread läuft.
Wenn debug
Trueist, wird die Ereignisschleife im Debug-Modus ausgeführt.Falsedeaktiviert den Debug-Modus explizit.Nonewird verwendet, um die globalen Einstellungen des Debug-Modus zu berücksichtigen.Wenn loop_factory nicht
Noneist, wird sie zur Erstellung einer neuen Ereignisschleife verwendet; andernfalls wirdasyncio.new_event_loop()verwendet. Die Schleife wird am Ende geschlossen. Diese Funktion sollte als Haupteinstiegspunkt für asyncio-Programme verwendet werden und idealerweise nur einmal aufgerufen werden. Es wird empfohlen, loop_factory zur Konfiguration der Ereignisschleife anstelle von Richtlinien zu verwenden. Die Übergabe vonasyncio.EventLoopermöglicht die Ausführung von asyncio ohne das Richtliniensystem.Der Executor erhält eine Timeout-Dauer von 5 Minuten zum Herunterfahren. Wenn der Executor innerhalb dieser Dauer nicht fertig ist, wird eine Warnung ausgegeben und der Executor geschlossen.
Beispiel
async def main(): await asyncio.sleep(1) print('hello') asyncio.run(main())
Hinzugefügt in Version 3.7.
Geändert in Version 3.9: Aktualisiert zur Verwendung von
loop.shutdown_default_executor().Geändert in Version 3.10: debug ist standardmäßig
None, um die globalen Einstellungen des Debug-Modus zu berücksichtigen.Geändert in Version 3.12: loop_factory-Parameter hinzugefügt.
Geändert in Version 3.14: coro kann jedes awaitable-Objekt sein.
Hinweis
Das
asyncio-Richtliniensystem ist veraltet und wird in Python 3.16 entfernt; danach ist ein expliziter loop_factory erforderlich, um die Ereignisschleife zu konfigurieren.
Runner-Kontextmanager¶
- class asyncio.Runner(*, debug=None, loop_factory=None)¶
Ein Kontextmanager, der die Ausführung von mehreren asynchronen Funktionsaufrufen im selben Kontext vereinfacht.
Manchmal sollten mehrere Top-Level-Async-Funktionen in derselben Ereignisschleife und demselben
contextvars.Contextaufgerufen werden.Wenn debug
Trueist, wird die Ereignisschleife im Debug-Modus ausgeführt.Falsedeaktiviert den Debug-Modus explizit.Nonewird verwendet, um die globalen Einstellungen des Debug-Modus zu berücksichtigen.loop_factory kann zur Überschreibung der Schleppenerstellung verwendet werden. Es liegt in der Verantwortung von loop_factory, die erstellte Schleife als aktuelle zu setzen. Standardmäßig wird
asyncio.new_event_loop()verwendet und mitasyncio.set_event_loop()als aktuelle Ereignisschleife gesetzt, wenn loop_factoryNoneist.Im Grunde kann das Beispiel von
asyncio.run()mit der Verwendung des Runners neu geschrieben werden.async def main(): await asyncio.sleep(1) print('hello') with asyncio.Runner() as runner: runner.run(main())
Hinzugefügt in Version 3.11.
- run(coro, *, context=None)¶
Führt coro in der eingebetteten Ereignisschleife aus.
Das Argument kann jedes awaitable-Objekt sein.
Wenn das Argument eine Coroutine ist, wird es in einen Task eingewickelt.
Ein optionales Keyword-only-Argument context erlaubt die Angabe eines benutzerdefinierten
contextvars.Context, in dem der Code ausgeführt werden soll. Der Standardkontext des Runners wird verwendet, wenn contextNoneist.Gibt das Ergebnis des awaitable zurück oder löst eine Ausnahme aus.
Diese Funktion kann nicht aufgerufen werden, wenn bereits eine andere asyncio-Ereignisschleife im selben Thread läuft.
Geändert in Version 3.14: coro kann jedes awaitable-Objekt sein.
- close()¶
Schließt den Runner.
Finalisiert asynchrone Generatoren, fährt den Standard-Executor herunter, schließt die Ereignisschleife und gibt eingebettete
contextvars.Contextfrei.
- get_loop()¶
Gibt die der Runner-Instanz zugeordnete Ereignisschleife zurück.
Hinweis
Runnerverwendet eine Strategie der verzögerten Initialisierung; sein Konstruktor initialisiert die zugrunde liegenden Low-Level-Strukturen nicht.Die eingebettete Schleife und der Kontext werden beim Eintritt in den
with-Block oder beim ersten Aufruf vonrun()oderget_loop()erstellt.
Behandlung von Tastaturunterbrechungen¶
Hinzugefügt in Version 3.11.
Wenn signal.SIGINT durch Strg-C ausgelöst wird, wird standardmäßig die Ausnahme KeyboardInterrupt im Hauptthread ausgelöst. Dies funktioniert jedoch nicht mit asyncio, da es interne asyncio-Abläufe unterbrechen kann und das Beenden des Programms blockieren kann.
Um dieses Problem zu beheben, behandelt asyncio signal.SIGINT wie folgt:
asyncio.Runner.run()installiert einen benutzerdefiniertensignal.SIGINT-Handler, bevor irgendein Benutzercode ausgeführt wird, und entfernt ihn beim Verlassen der Funktion wieder.Der
Runnererstellt den Haupt-Task für die übergebene Coroutine zur Ausführung.Wenn
signal.SIGINTdurch Strg-C ausgelöst wird, bricht der benutzerdefinierte Signal-Handler den Haupt-Task ab, indem erasyncio.Task.cancel()aufruft, wasasyncio.CancelledErrorinnerhalb des Haupt-Tasks auslöst. Dies führt zum Auswickeln des Python-Stacks;try/except- undtry/finally-Blöcke können für die Ressourcenbereinigung verwendet werden. Nachdem der Haupt-Task abgebrochen wurde, löstasyncio.Runner.run()KeyboardInterruptaus.Ein Benutzer könnte eine enge Schleife schreiben, die nicht durch
asyncio.Task.cancel()unterbrochen werden kann, in diesem Fall löst die zweite nachfolgende Strg-C-Betätigung sofort dieKeyboardInterruptaus, ohne den Haupt-Task abzubrechen.