Coroutinen und Tasks

Dieser Abschnitt beschreibt High-Level asyncio APIs zur Arbeit mit Coroutinen und Tasks.

Coroutinen

Quellcode: Lib/asyncio/coroutines.py


Coroutinen, die mit der async/await-Syntax deklariert sind, sind der bevorzugte Weg, um asyncio-Anwendungen zu schreiben. Zum Beispiel gibt der folgende Code-Schnipsel „hello“ aus, wartet 1 Sekunde und gibt dann „world“ aus.

>>> import asyncio

>>> async def main():
...     print('hello')
...     await asyncio.sleep(1)
...     print('world')

>>> asyncio.run(main())
hello
world

Beachten Sie, dass das bloße Aufrufen einer Coroutine diese nicht zur Ausführung plant.

>>> main()
<coroutine object main at 0x1053bb7c8>

Um eine Coroutine tatsächlich auszuführen, bietet asyncio die folgenden Mechanismen:

  • Die Funktion asyncio.run(), um die primäre Einstiegsfunktion „main()“ auszuführen (siehe obiges Beispiel).

  • Awaiten auf einer Coroutine. Der folgende Code-Schnipsel gibt nach einer Wartezeit von 1 Sekunde „hello“ aus und dann nach einer *weiteren* Wartezeit von 2 Sekunden „world“.

    import asyncio
    import time
    
    async def say_after(delay, what):
        await asyncio.sleep(delay)
        print(what)
    
    async def main():
        print(f"started at {time.strftime('%X')}")
    
        await say_after(1, 'hello')
        await say_after(2, 'world')
    
        print(f"finished at {time.strftime('%X')}")
    
    asyncio.run(main())
    

    Erwartete Ausgabe

    started at 17:13:52
    hello
    world
    finished at 17:13:55
    
  • Die Funktion asyncio.create_task(), um Coroutinen parallel als asyncio Tasks auszuführen.

    Lassen Sie uns das obige Beispiel modifizieren und zwei say_after Coroutinen *parallel* ausführen.

    async def main():
        task1 = asyncio.create_task(
            say_after(1, 'hello'))
    
        task2 = asyncio.create_task(
            say_after(2, 'world'))
    
        print(f"started at {time.strftime('%X')}")
    
        # Wait until both tasks are completed (should take
        # around 2 seconds.)
        await task1
        await task2
    
        print(f"finished at {time.strftime('%X')}")
    

    Beachten Sie, dass die erwartete Ausgabe nun zeigt, dass der Schnipsel 1 Sekunde schneller läuft als zuvor.

    started at 17:14:32
    hello
    world
    finished at 17:14:34
    
  • Die Klasse asyncio.TaskGroup bietet eine modernere Alternative zu create_task(). Mit dieser API wird das letzte Beispiel zu

    async def main():
        async with asyncio.TaskGroup() as tg:
            task1 = tg.create_task(
                say_after(1, 'hello'))
    
            task2 = tg.create_task(
                say_after(2, 'world'))
    
            print(f"started at {time.strftime('%X')}")
    
        # The await is implicit when the context manager exits.
    
        print(f"finished at {time.strftime('%X')}")
    

    Das Timing und die Ausgabe sollten mit der vorherigen Version übereinstimmen.

    Hinzugefügt in Version 3.11: asyncio.TaskGroup.

Awaitables

Wir sagen, dass ein Objekt ein awaitable Objekt ist, wenn es in einem await-Ausdruck verwendet werden kann. Viele asyncio APIs sind so konzipiert, dass sie awaitables akzeptieren.

Es gibt drei Haupttypen von awaitable Objekten: Coroutinen, Tasks und Futures.

Coroutinen

Python-Coroutinen sind awaitables und können daher von anderen Coroutinen awaited werden.

import asyncio

async def nested():
    return 42

async def main():
    # Nothing happens if we just call "nested()".
    # A coroutine object is created but not awaited,
    # so it *won't run at all*.
    nested()  # will raise a "RuntimeWarning".

    # Let's do it differently now and await it:
    print(await nested())  # will print "42".

asyncio.run(main())

Wichtig

In dieser Dokumentation kann der Begriff „Coroutine“ für zwei eng verwandte Konzepte verwendet werden:

  • eine Coroutine-Funktion: eine async def Funktion;

  • ein Coroutine-Objekt: ein Objekt, das durch Aufrufen einer Coroutine-Funktion zurückgegeben wird.

Tasks

Tasks werden verwendet, um Coroutinen *parallel* zu planen.

Wenn eine Coroutine mit Funktionen wie asyncio.create_task() in einen Task eingewickelt wird, wird die Coroutine automatisch bald zur Ausführung geplant.

import asyncio

async def nested():
    return 42

async def main():
    # Schedule nested() to run soon concurrently
    # with "main()".
    task = asyncio.create_task(nested())

    # "task" can now be used to cancel "nested()", or
    # can simply be awaited to wait until it is complete:
    await task

asyncio.run(main())

Futures

Ein Future ist ein spezielles Low-Level awaitable Objekt, das ein zukünftiges Ergebnis einer asynchronen Operation darstellt.

Wenn ein Future-Objekt awaited wird, bedeutet dies, dass die Coroutine wartet, bis das Future an anderer Stelle aufgelöst ist.

Future-Objekte in asyncio werden benötigt, um Callback-basierte Codes mit async/await verwenden zu können.

Normalerweise gibt es keinen Bedarf, Future-Objekte im Anwendungslevel-Code zu erstellen.

Future-Objekte, die manchmal von Bibliotheken und einigen asyncio APIs offengelegt werden, können awaited werden.

async def main():
    await function_that_returns_a_future_object()

    # this is also valid:
    await asyncio.gather(
        function_that_returns_a_future_object(),
        some_python_coroutine()
    )

Ein gutes Beispiel für eine Low-Level-Funktion, die ein Future-Objekt zurückgibt, ist loop.run_in_executor().

Tasks erstellen

Quellcode: Lib/asyncio/tasks.py


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

Wickelt die coro Coroutine in einen Task ein und plant dessen Ausführung. Gibt das Task-Objekt zurück.

Die vollständige Funktionssignatur ist weitgehend identisch mit der des Task-Konstruktors (oder Factories) – alle Schlüsselwortargumente an diese Funktion werden an diese Schnittstelle weitergeleitet.

Ein optionales schlüsselwort-only context Argument erlaubt die Angabe eines benutzerdefinierten contextvars.Context für die Ausführung der coro. Die aktuelle Kontextkopie wird erstellt, wenn kein context bereitgestellt wird.

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

Der Task wird in der von get_running_loop() zurückgegebenen Schleife ausgeführt. RuntimeError wird ausgelöst, wenn in diesem Thread keine laufende Schleife vorhanden ist.

Hinweis

asyncio.TaskGroup.create_task() ist eine neue Alternative, die strukturelle Konkurrenz nutzt; sie ermöglicht das Warten auf eine Gruppe verwandter Tasks mit starken Sicherheitsgarantien.

Wichtig

Speichern Sie eine Referenz auf das Ergebnis dieser Funktion, um zu verhindern, dass ein Task mitten in der Ausführung verschwindet. Die Ereignisschleife hält nur schwache Referenzen auf Tasks. Ein Task, auf den sonst nirgends Bezug genommen wird, kann jederzeit vom Garbage Collector entfernt werden, noch bevor er beendet ist. Für zuverlässige „Fire-and-Forget“-Hintergrundtasks sammeln Sie sie in einer Collection.

background_tasks = set()

for i in range(10):
    task = asyncio.create_task(some_coro(param=i))

    # Add task to the set. This creates a strong reference.
    background_tasks.add(task)

    # To prevent keeping references to finished tasks forever,
    # make each task remove its own reference from the set after
    # completion:
    task.add_done_callback(background_tasks.discard)

Hinzugefügt in Version 3.7.

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

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

Geändert in Version 3.14: Parameter eager_start hinzugefügt durch Weiterleitung aller kwargs.

Task-Abbruch

Tasks können einfach und sicher abgebrochen werden. Wenn ein Task abgebrochen wird, wird asyncio.CancelledError beim nächsten Gelegenheitsereignis im Task ausgelöst.

Es wird empfohlen, dass Coroutinen try/finally-Blöcke verwenden, um Bereinigungslogik robust durchzuführen. Falls asyncio.CancelledError explizit abgefangen wird, sollte er nach Abschluss der Bereinigung im Allgemeinen weitergegeben werden. asyncio.CancelledError ist eine direkte Unterklasse von BaseException, sodass die meisten Codes sich dessen bewusst sein müssen.

Die asyncio-Komponenten, die strukturelle Konkurrenz ermöglichen, wie asyncio.TaskGroup und asyncio.timeout(), werden intern mit Abbruch implementiert und können sich falsch verhalten, wenn eine Coroutine asyncio.CancelledError verschluckt. Ebenso sollten Benutzeroberflächen-Codes im Allgemeinen uncancel nicht aufrufen. In Fällen, in denen die Unterdrückung von asyncio.CancelledError tatsächlich gewünscht ist, ist es jedoch notwendig, auch uncancel() aufzurufen, um den Abbruchstatus vollständig zu entfernen.

Task-Gruppen

Task-Gruppen kombinieren eine API zur Task-Erstellung mit einer bequemen und zuverlässigen Möglichkeit, auf die Fertigstellung aller Tasks in der Gruppe zu warten.

class asyncio.TaskGroup

Ein asynchroner Kontextmanager, der eine Gruppe von Tasks enthält. Tasks können der Gruppe mit create_task() hinzugefügt werden. Alle Tasks werden awaited, wenn der Kontextmanager beendet wird.

Hinzugefügt in Version 3.11.

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

Erstellt einen Task in dieser Task-Gruppe. Die Signatur entspricht der von asyncio.create_task(). Wenn die Task-Gruppe inaktiv ist (z.B. noch nicht betreten, bereits beendet oder im Prozess des Herunterfahrens), wird die gegebene coro geschlossen.

Geändert in Version 3.13: Schließt die gegebene Coroutine, wenn die Task-Gruppe nicht aktiv ist.

Geändert in Version 3.14: Leitet alle kwargs an loop.create_task() weiter.

Beispiel

async def main():
    async with asyncio.TaskGroup() as tg:
        task1 = tg.create_task(some_coro(...))
        task2 = tg.create_task(another_coro(...))
    print(f"Both tasks have completed now: {task1.result()}, {task2.result()}")

Die Anweisung async with wartet, bis alle Tasks in der Gruppe fertig sind. Während des Wartens können noch neue Tasks zur Gruppe hinzugefügt werden (z. B. indem tg in eine der Coroutinen übergeben und tg.create_task() in dieser Coroutine aufgerufen wird). Sobald der letzte Task beendet ist und der async with-Block verlassen wird, können keine neuen Tasks mehr zur Gruppe hinzugefügt werden.

Wenn der erste Task, der zu der Gruppe gehört, mit einer Ausnahme außer asyncio.CancelledError fehlschlägt, werden die übrigen Tasks in der Gruppe abgebrochen. Es können dann keine weiteren Tasks zur Gruppe hinzugefügt werden. Wenn zu diesem Zeitpunkt der Körper des async with-Blocks noch aktiv ist (d. h. __aexit__() noch nicht aufgerufen wurde), wird auch der Task, der den async with-Block direkt enthält, abgebrochen. Das resultierende asyncio.CancelledError unterbricht ein await, wird aber nicht aus dem umschließenden async with-Block herausblubbern.

Sobald alle Tasks abgeschlossen sind, und falls einige Tasks mit einer Ausnahme außer asyncio.CancelledError fehlgeschlagen sind, werden diese Ausnahmen in einer ExceptionGroup oder BaseExceptionGroup (je nach Bedarf; siehe deren Dokumentation) kombiniert, die dann ausgelöst wird.

Zwei Basis-Ausnahmen werden speziell behandelt: Wenn ein Task mit KeyboardInterrupt oder SystemExit fehlschlägt, bricht die Task-Gruppe die verbleibenden Tasks immer noch ab und wartet auf sie, aber dann wird die ursprüngliche KeyboardInterrupt oder SystemExit anstelle von ExceptionGroup oder BaseExceptionGroup neu ausgelöst.

Wenn der Körper des async with-Blocks mit einer Ausnahme beendet wird (sodass __aexit__() mit einer gesetzten Ausnahme aufgerufen wird), wird dies genauso behandelt, als ob einer der Tasks fehlgeschlagen wäre: Die verbleibenden Tasks werden abgebrochen und dann abgewartet, und Nicht-Abbruch-Ausnahmen werden zu einer Ausnahme-Gruppe zusammengefasst und ausgelöst. Die Ausnahme, die in __aexit__() übergeben wird, sofern sie nicht asyncio.CancelledError ist, wird ebenfalls in die Ausnahme-Gruppe aufgenommen. Der gleiche Sonderfall wird für KeyboardInterrupt und SystemExit wie im vorherigen Absatz gemacht.

Task-Gruppen mischen den internen Abbruch, der dazu dient, ihre __aexit__() „aufzuwecken“, nicht mit Abbruch-Anfragen für den Task, in dem sie laufen und die von anderen Parteien gemacht werden. Insbesondere, wenn eine Task-Gruppe in eine andere verschachtelt ist und beide gleichzeitig eine Ausnahme in einem ihrer Kind-Tasks erfahren, verarbeitet die innere Task-Gruppe ihre Ausnahmen, und dann empfängt die äußere Task-Gruppe einen weiteren Abbruch und verarbeitet ihre eigenen Ausnahmen.

Wenn eine Task-Gruppe extern abgebrochen wird und auch eine ExceptionGroup auslösen muss, wird die cancel()-Methode des Eltern-Tasks aufgerufen. Dies stellt sicher, dass ein asyncio.CancelledError beim nächsten await ausgelöst wird, sodass der Abbruch nicht verloren geht.

Task-Gruppen erhalten die Abbruch-Zählung, die von asyncio.Task.cancelling() gemeldet wird.

Geändert in Version 3.13: Verbesserte Handhabung gleichzeitiger interner und externer Abbrüche und korrekte Beibehaltung der Abbruch-Zählungen.

Beenden einer Task-Gruppe

Obwohl das Beenden einer Task-Gruppe von der Standardbibliothek nicht nativ unterstützt wird, kann ein Beenden erreicht werden, indem ein Ausnahmen auslösender Task zur Task-Gruppe hinzugefügt und die ausgelöste Ausnahme ignoriert wird.

import asyncio
from asyncio import TaskGroup

class TerminateTaskGroup(Exception):
    """Exception raised to terminate a task group."""

async def force_terminate_task_group():
    """Used to force termination of a task group."""
    raise TerminateTaskGroup()

async def job(task_id, sleep_time):
    print(f'Task {task_id}: start')
    await asyncio.sleep(sleep_time)
    print(f'Task {task_id}: done')

async def main():
    try:
        async with TaskGroup() as group:
            # spawn some tasks
            group.create_task(job(1, 0.5))
            group.create_task(job(2, 1.5))
            # sleep for 1 second
            await asyncio.sleep(1)
            # add an exception-raising task to force the group to terminate
            group.create_task(force_terminate_task_group())
    except* TerminateTaskGroup:
        pass

asyncio.run(main())

Erwartete Ausgabe

Task 1: start
Task 2: start
Task 1: done

Schlafen

async asyncio.sleep(delay, result=None)

Blockiere für delay Sekunden.

Wenn result angegeben ist, wird es an den Aufrufer zurückgegeben, wenn die Coroutine abgeschlossen ist.

sleep() suspendiert immer den aktuellen Task und erlaubt anderen Tasks, ausgeführt zu werden.

Das Setzen der Verzögerung auf 0 bietet einen optimierten Pfad, um anderen Tasks die Ausführung zu ermöglichen. Dies kann von lang laufenden Funktionen verwendet werden, um zu vermeiden, dass die Ereignisschleife für die gesamte Dauer des Funktionsaufrufs blockiert wird.

Beispiel einer Coroutine, die 5 Sekunden lang jede Sekunde das aktuelle Datum anzeigt

import asyncio
import datetime

async def display_date():
    loop = asyncio.get_running_loop()
    end_time = loop.time() + 5.0
    while True:
        print(datetime.datetime.now())
        if (loop.time() + 1.0) >= end_time:
            break
        await asyncio.sleep(1)

asyncio.run(display_date())

Geändert in Version 3.10: Das Argument loop wurde entfernt.

Geändert in Version 3.13: Löst ValueError aus, wenn delay nan ist.

Tasks parallel ausführen

awaitable asyncio.gather(*aws, return_exceptions=False)

Führt awaitable objects in der aws-Sequenz *parallel* aus.

Wenn ein awaitable in aws eine Coroutine ist, wird es automatisch als Task geplant.

Wenn alle awaitables erfolgreich abgeschlossen sind, ist das Ergebnis eine aggregierte Liste der zurückgegebenen Werte. Die Reihenfolge der Ergebniswerte entspricht der Reihenfolge der awaitables in aws.

Wenn return_exceptions auf False (Standard) gesetzt ist, wird die erste ausgelöste Ausnahme sofort an den Task weitergegeben, der auf gather() wartet. Andere awaitables in der aws-Sequenz werden **nicht abgebrochen** und laufen weiter.

Wenn return_exceptions auf True gesetzt ist, werden Ausnahmen wie erfolgreiche Ergebnisse behandelt und in der Ergebnisliste aggregiert.

Wenn gather() *abgebrochen* wird, werden alle übergebenen awaitables (die noch nicht abgeschlossen sind) ebenfalls abgebrochen.

Wenn ein Task oder Future aus der aws-Sequenz *abgebrochen* wird, wird dies so behandelt, als ob es CancelledError ausgelöst hätte – der gather()-Aufruf wird in diesem Fall **nicht** abgebrochen. Dies soll verhindern, dass der Abbruch eines übergebenen Tasks/Futures andere Tasks/Futures abbricht.

Hinweis

Eine neue Alternative zum Erstellen und Ausführen von Tasks parallel und zum Warten auf deren Abschluss ist asyncio.TaskGroup. TaskGroup bietet stärkere Sicherheitsgarantien als gather für die Planung einer Verschachtelung von Untertasks: Wenn ein Task (oder ein Untertask, ein von einem Task geplanter Task) eine Ausnahme auslöst, bricht TaskGroup die verbleibenden geplanten Tasks ab, während gather dies nicht tut.

Beispiel

import asyncio

async def factorial(name, number):
    f = 1
    for i in range(2, number + 1):
        print(f"Task {name}: Compute factorial({number}), currently i={i}...")
        await asyncio.sleep(1)
        f *= i
    print(f"Task {name}: factorial({number}) = {f}")
    return f

async def main():
    # Schedule three calls *concurrently*:
    L = await asyncio.gather(
        factorial("A", 2),
        factorial("B", 3),
        factorial("C", 4),
    )
    print(L)

asyncio.run(main())

# Expected output:
#
#     Task A: Compute factorial(2), currently i=2...
#     Task B: Compute factorial(3), currently i=2...
#     Task C: Compute factorial(4), currently i=2...
#     Task A: factorial(2) = 2
#     Task B: Compute factorial(3), currently i=3...
#     Task C: Compute factorial(4), currently i=3...
#     Task B: factorial(3) = 6
#     Task C: Compute factorial(4), currently i=4...
#     Task C: factorial(4) = 24
#     [2, 6, 24]

Hinweis

Wenn return_exceptions falsch ist, bricht das Abbrechen von gather(), nachdem es als erledigt markiert wurde, keine übergebenen awaitables ab. Zum Beispiel kann gather() als erledigt markiert werden, nachdem eine Ausnahme an den Aufrufer weitergegeben wurde. Daher bricht der Aufruf von gather.cancel() nach dem Abfangen einer Ausnahme (die von einem der awaitables ausgelöst wurde) von gather keine anderen awaitables ab.

Geändert in Version 3.7: Wenn gather() selbst abgebrochen wird, wird der Abbruch unabhängig von return_exceptions weitergegeben.

Geändert in Version 3.10: Das Argument loop wurde entfernt.

Veraltet seit Version 3.10: Es wird eine Deprecation-Warnung ausgegeben, wenn keine positionsbezogenen Argumente bereitgestellt werden oder nicht alle positionsbezogenen Argumente zukunftsähnliche Objekte sind und keine laufende Ereignisschleife vorhanden ist.

Eager Task Factory

asyncio.eager_task_factory(loop, coro, *, name=None, context=None)

Eine Task-Factory für sofortige Task-Ausführung.

Bei Verwendung dieser Factory (über loop.set_task_factory(asyncio.eager_task_factory)) beginnen Coroutinen synchron während der Konstruktion von Task. Tasks werden nur dann in die Ereignisschleife geplant, wenn sie blockieren. Dies kann eine Leistungsverbesserung sein, da der Overhead der Schleifenplanung für Coroutinen vermieden wird, die synchron abgeschlossen werden.

Ein gängiges Beispiel, bei dem dies von Vorteil ist, sind Coroutinen, die Caching oder Memoisation verwenden, um tatsächliche I/O-Operationen zu vermeiden, wenn möglich.

Hinweis

Die sofortige Ausführung der Coroutine ist eine semantische Änderung. Wenn die Coroutine zurückkehrt oder eine Ausnahme auslöst, wird der Task nie in die Ereignisschleife geplant. Wenn die Ausführung der Coroutine blockiert, wird der Task in die Ereignisschleife geplant. Diese Änderung kann zu Verhaltensänderungen in bestehenden Anwendungen führen. Zum Beispiel wird die Task-Ausführungsreihenfolge der Anwendung wahrscheinlich geändert.

Hinzugefügt in Version 3.12.

asyncio.create_eager_task_factory(custom_task_constructor)

Erstellt eine „eager“-Task-Factory, ähnlich wie eager_task_factory(), wobei der bereitgestellte custom_task_constructor bei der Erstellung eines neuen Tasks anstelle des Standard-Task verwendet wird.

custom_task_constructor muss ein Callable sein, dessen Signatur mit der Signatur von Task.__init__ übereinstimmt. Das Callable muss ein asyncio.Task-kompatibles Objekt zurückgeben.

Diese Funktion gibt ein Callable zurück, das als Task-Factory einer Ereignisschleife über loop.set_task_factory(factory) verwendet werden kann.

Hinzugefügt in Version 3.12.

Vor Abbruch schützen

awaitable asyncio.shield(aw)

Schützt ein awaitable Objekt davor, *abgebrochen* zu werden (cancel()).

Wenn aw eine Coroutine ist, wird sie automatisch als Task geplant.

Die Anweisung

task = asyncio.create_task(something())
res = await shield(task)

gleichbedeutend ist mit

res = await something()

außer dass, wenn die enthaltende Koroutine abgebrochen wird, die in something() laufende Aufgabe nicht abgebrochen wird. Aus der Sicht von something() fand der Abbruch nicht statt. Obwohl ihr Aufrufer immer noch abgebrochen wird, löst der "await"-Ausdruck immer noch einen CancelledError aus.

Wenn something() aus anderen Gründen abgebrochen wird (d. h. aus sich selbst heraus), würde dies auch shield() abbrechen.

Wenn der Abbruch vollständig ignoriert werden soll (nicht empfohlen), sollte die Funktion shield() mit einer try/except-Klausel kombiniert werden, wie folgt:

task = asyncio.create_task(something())
try:
    res = await shield(task)
except CancelledError:
    res = None

Wichtig

Speichern Sie eine Referenz auf Aufgaben, die dieser Funktion übergeben werden, um zu vermeiden, dass eine Aufgabe mitten in der Ausführung verschwindet. Die Event-Schleife behält nur schwache Referenzen auf Aufgaben. Eine Aufgabe, auf die anderweitig nicht verwiesen wird, kann jederzeit gesammelt werden, auch bevor sie abgeschlossen ist.

Geändert in Version 3.10: Das Argument loop wurde entfernt.

Veraltet seit Version 3.10: Eine Deprecation-Warnung wird ausgegeben, wenn aw kein zukunftsähnliches Objekt ist und keine laufende Event-Schleife vorhanden ist.

Timeouts

asyncio.timeout(delay)

Gibt einen asynchronen Kontextmanager zurück, der verwendet werden kann, um die Zeit zu begrenzen, die mit dem Warten auf etwas verbracht wird.

delay kann entweder None oder eine Fließkommazahl/Ganzzahl in Sekunden sein, um zu warten. Wenn delay None ist, wird keine Zeitbegrenzung angewendet; dies kann nützlich sein, wenn die Verzögerung unbekannt ist, wenn der Kontextmanager erstellt wird.

In beiden Fällen kann der Kontextmanager nach der Erstellung mit Timeout.reschedule() neu geplant werden.

Beispiel

async def main():
    async with asyncio.timeout(10):
        await long_running_task()

Wenn die Ausführung von long_running_task länger als 10 Sekunden dauert, wird der Kontextmanager die aktuelle Aufgabe abbrechen und den resultierenden asyncio.CancelledError intern behandeln und in einen TimeoutError umwandeln, der abgefangen und behandelt werden kann.

Hinweis

Der Kontextmanager asyncio.timeout() ist derjenige, der den asyncio.CancelledError in einen TimeoutError umwandelt. Das bedeutet, dass der TimeoutError nur außerhalb des Kontextmanagers abgefangen werden kann.

Beispiel für das Abfangen von TimeoutError

async def main():
    try:
        async with asyncio.timeout(10):
            await long_running_task()
    except TimeoutError:
        print("The long operation timed out, but we've handled it.")

    print("This statement will run regardless.")

Der von asyncio.timeout() erzeugte Kontextmanager kann auf eine andere Frist neu geplant und inspiziert werden.

class asyncio.Timeout(when)

Ein asynchroner Kontextmanager zum Abbrechen überfälliger Koroutinen.

when sollte eine absolute Zeit sein, zu der der Kontext abläuft, gemessen an der Uhr der Event-Schleife.

  • Wenn when None ist, wird der Timeout niemals ausgelöst.

  • Wenn when < loop.time(), wird der Timeout bei der nächsten Iteration der Event-Schleife ausgelöst.

when() float | None

Gibt die aktuelle Frist zurück oder None, wenn die aktuelle Frist nicht gesetzt ist.

reschedule(when: float | None)

Plant den Timeout neu.

expired() bool

Gibt zurück, ob der Kontextmanager seine Frist überschritten hat (abgelaufen ist).

Beispiel

async def main():
    try:
        # We do not know the timeout when starting, so we pass ``None``.
        async with asyncio.timeout(None) as cm:
            # We know the timeout now, so we reschedule it.
            new_deadline = get_running_loop().time() + 10
            cm.reschedule(new_deadline)

            await long_running_task()
    except TimeoutError:
        pass

    if cm.expired():
        print("Looks like we haven't finished on time.")

Timeout-Kontextmanager können sicher verschachtelt werden.

Hinzugefügt in Version 3.11.

asyncio.timeout_at(when)

Ähnlich wie asyncio.timeout(), mit der Ausnahme, dass when die absolute Zeit ist, zu der mit dem Warten aufgehört werden soll, oder None ist.

Beispiel

async def main():
    loop = get_running_loop()
    deadline = loop.time() + 20
    try:
        async with asyncio.timeout_at(deadline):
            await long_running_task()
    except TimeoutError:
        print("The long operation timed out, but we've handled it.")

    print("This statement will run regardless.")

Hinzugefügt in Version 3.11.

async asyncio.wait_for(aw, timeout)

Wartet darauf, dass das awaitable-Objekt aw mit einem Timeout abgeschlossen wird.

Wenn aw eine Coroutine ist, wird sie automatisch als Task geplant.

timeout kann entweder None oder eine Fließkommazahl oder Ganzzahl in Sekunden sein, um zu warten. Wenn timeout None ist, blockiert, bis die Zukunft abgeschlossen ist.

Wenn ein Timeout auftritt, wird die Aufgabe abgebrochen und ein TimeoutError ausgelöst.

Um den Abbruch der Aufgabe zu vermeiden, wickeln Sie sie in shield() ein.

Die Funktion wartet, bis die Zukunft tatsächlich abgebrochen wurde, sodass die gesamte Wartezeit die timeout-Dauer überschreiten kann. Wenn während des Abbrechens ein Fehler auftritt, wird dieser weitergegeben.

Wenn das Warten abgebrochen wird, wird die Zukunft aw ebenfalls abgebrochen.

Beispiel

async def eternity():
    # Sleep for one hour
    await asyncio.sleep(3600)
    print('yay!')

async def main():
    # Wait for at most 1 second
    try:
        await asyncio.wait_for(eternity(), timeout=1.0)
    except TimeoutError:
        print('timeout!')

asyncio.run(main())

# Expected output:
#
#     timeout!

Geändert in Version 3.7: Wenn aw aufgrund eines Timeouts abgebrochen wird, wartet wait_for darauf, dass aw abgebrochen wird. Zuvor wurde sofort ein TimeoutError ausgelöst.

Geändert in Version 3.10: Das Argument loop wurde entfernt.

Geändert in Version 3.11: Löst stattdessen TimeoutError statt asyncio.TimeoutError aus.

Warte-Primitive

async asyncio.wait(aws, *, timeout=None, return_when=ALL_COMPLETED)

Führt Future- und Task-Instanzen im Iterable aws gleichzeitig aus und blockiert, bis die Bedingung, die durch return_when angegeben ist, erfüllt ist.

Das Iterable aws darf nicht leer sein.

Gibt zwei Mengen von Tasks/Futures zurück: (done, pending).

Verwendung

done, pending = await asyncio.wait(aws)

timeout (eine Fließkommazahl oder Ganzzahl) kann, falls angegeben, verwendet werden, um die maximale Anzahl von Sekunden zu steuern, bevor zurückgekehrt wird.

Beachten Sie, dass diese Funktion keinen TimeoutError auslöst. Futures oder Tasks, die zum Zeitpunkt des Timeouts noch nicht abgeschlossen sind, werden einfach in der zweiten Menge zurückgegeben.

return_when gibt an, wann diese Funktion zurückkehren soll. Es muss eine der folgenden Konstanten sein:

Konstante

Beschreibung

asyncio.FIRST_COMPLETED

Die Funktion gibt zurück, wenn ein Future abgeschlossen oder abgebrochen wird.

asyncio.FIRST_EXCEPTION

Die Funktion gibt zurück, wenn ein Future durch Auslösen einer Ausnahme abgeschlossen wird. Wenn kein Future eine Ausnahme auslöst, ist dies äquivalent zu ALL_COMPLETED.

asyncio.ALL_COMPLETED

Die Funktion gibt zurück, wenn alle Futures abgeschlossen oder abgebrochen sind.

Im Gegensatz zu wait_for() bricht wait() die Futures bei einem Timeout nicht ab.

Geändert in Version 3.10: Das Argument loop wurde entfernt.

Geändert in Version 3.11: Das direkte Übergeben von Koroutinen-Objekten an wait() ist verboten.

Geändert in Version 3.12: Unterstützung für Generatoren hinzugefügt, die Tasks liefern.

asyncio.as_completed(aws, *, timeout=None)

Führt awaitable-Objekte im Iterable aws gleichzeitig aus. Das zurückgegebene Objekt kann iteriert werden, um die Ergebnisse der awaitables zu erhalten, sobald sie abgeschlossen sind.

Das von as_completed() zurückgegebene Objekt kann als asynchroner Iterator oder als einfacher Iterator iteriert werden. Wenn eine asynchrone Iteration verwendet wird, werden die ursprünglich bereitgestellten awaitables zurückgegeben, wenn sie Tasks oder Futures sind. Dies erleichtert die Korrelation von zuvor geplanten Tasks mit ihren Ergebnissen. Beispiel:

ipv4_connect = create_task(open_connection("127.0.0.1", 80))
ipv6_connect = create_task(open_connection("::1", 80))
tasks = [ipv4_connect, ipv6_connect]

async for earliest_connect in as_completed(tasks):
    # earliest_connect is done. The result can be obtained by
    # awaiting it or calling earliest_connect.result()
    reader, writer = await earliest_connect

    if earliest_connect is ipv6_connect:
        print("IPv6 connection established.")
    else:
        print("IPv4 connection established.")

Während der asynchronen Iteration werden implizit erstellte Tasks für bereitgestellte awaitables zurückgegeben, die keine Tasks oder Futures sind.

Wenn es als einfacher Iterator verwendet wird, gibt jede Iteration eine neue Koroutine zurück, die das Ergebnis der nächsten abgeschlossenen Awaitable zurückgibt oder die Ausnahme auslöst. Dieses Muster ist mit Python-Versionen vor 3.13 kompatibel.

ipv4_connect = create_task(open_connection("127.0.0.1", 80))
ipv6_connect = create_task(open_connection("::1", 80))
tasks = [ipv4_connect, ipv6_connect]

for next_connect in as_completed(tasks):
    # next_connect is not one of the original task objects. It must be
    # awaited to obtain the result value or raise the exception of the
    # awaitable that finishes next.
    reader, writer = await next_connect

Ein TimeoutError wird ausgelöst, wenn der Timeout auftritt, bevor alle awaitables abgeschlossen sind. Dies wird durch die async for-Schleife während der asynchronen Iteration oder durch die während der einfachen Iteration zurückgegebenen Koroutinen ausgelöst.

Geändert in Version 3.10: Das Argument loop wurde entfernt.

Veraltet seit Version 3.10: Eine Deprecation-Warnung wird ausgegeben, wenn nicht alle awaitable-Objekte im Iterable aws zukunftsähnliche Objekte sind und keine laufende Event-Schleife vorhanden ist.

Geändert in Version 3.12: Unterstützung für Generatoren hinzugefügt, die Tasks liefern.

Geändert in Version 3.13: Das Ergebnis kann jetzt entweder als asynchroner Iterator oder als einfacher Iterator verwendet werden (zuvor war es nur ein einfacher Iterator).

Ausführung in Threads

async asyncio.to_thread(func, /, *args, **kwargs)

Führt die Funktion func asynchron in einem separaten Thread aus.

Alle für diese Funktion bereitgestellten *args und **kwargs werden direkt an func übergeben. Außerdem wird der aktuelle contextvars.Context propagiert, sodass Variablen aus dem Kontext des Event-Loops im separaten Thread zugänglich sind.

Gibt eine Koroutine zurück, die awaitet werden kann, um das Endergebnis von func zu erhalten.

Diese Koroutinenfunktion ist hauptsächlich für die Ausführung von E/A-gebundenen Funktionen/Methoden gedacht, die andernfalls die Event-Schleife blockieren würden, wenn sie im Hauptthread ausgeführt würden. Zum Beispiel:

def blocking_io():
    print(f"start blocking_io at {time.strftime('%X')}")
    # Note that time.sleep() can be replaced with any blocking
    # IO-bound operation, such as file operations.
    time.sleep(1)
    print(f"blocking_io complete at {time.strftime('%X')}")

async def main():
    print(f"started main at {time.strftime('%X')}")

    await asyncio.gather(
        asyncio.to_thread(blocking_io),
        asyncio.sleep(1))

    print(f"finished main at {time.strftime('%X')}")


asyncio.run(main())

# Expected output:
#
# started main at 19:50:53
# start blocking_io at 19:50:53
# blocking_io complete at 19:50:54
# finished main at 19:50:54

Direktes Aufrufen von blocking_io() in einer beliebigen Koroutine würde die Event-Schleife für ihre Dauer blockieren, was zu einer zusätzlichen Laufzeit von 1 Sekunde führt. Stattdessen können wir durch die Verwendung von asyncio.to_thread() sie in einem separaten Thread ausführen, ohne die Event-Schleife zu blockieren.

Hinweis

Aufgrund des GIL kann asyncio.to_thread() typischerweise nur verwendet werden, um E/A-gebundene Funktionen nicht-blockierend zu machen. Für Erweiterungsmodule, die das GIL freigeben, oder für alternative Python-Implementierungen, die kein GIL haben, kann asyncio.to_thread() auch für CPU-gebundene Funktionen verwendet werden.

Hinzugefügt in Version 3.9.

Planung aus anderen Threads

asyncio.run_coroutine_threadsafe(coro, loop)

Übergibt eine Koroutine an die angegebene Event-Schleife. Thread-sicher.

Gibt eine concurrent.futures.Future zurück, um auf das Ergebnis aus einem anderen Betriebssystem-Thread zu warten.

Diese Funktion ist dafür gedacht, von einem anderen Betriebssystem-Thread als dem aufgerufen zu werden, in dem die Event-Schleife läuft. Beispiel:

def in_thread(loop: asyncio.AbstractEventLoop) -> None:
    # Run some blocking IO
    pathlib.Path("example.txt").write_text("hello world", encoding="utf8")

    # Create a coroutine
    coro = asyncio.sleep(1, result=3)

    # Submit the coroutine to a given loop
    future = asyncio.run_coroutine_threadsafe(coro, loop)

    # Wait for the result with an optional timeout argument
    assert future.result(timeout=2) == 3

async def amain() -> None:
    # Get the running loop
    loop = asyncio.get_running_loop()

    # Run something in a thread
    await asyncio.to_thread(in_thread, loop)

Es ist auch möglich, den umgekehrten Weg zu gehen. Beispiel:

@contextlib.contextmanager
def loop_in_thread() -> Generator[asyncio.AbstractEventLoop]:
    loop_fut = concurrent.futures.Future[asyncio.AbstractEventLoop]()
    stop_event = asyncio.Event()

    async def main() -> None:
        loop_fut.set_result(asyncio.get_running_loop())
        await stop_event.wait()

    with concurrent.futures.ThreadPoolExecutor(1) as tpe:
        complete_fut = tpe.submit(asyncio.run, main())
        for fut in concurrent.futures.as_completed((loop_fut, complete_fut)):
            if fut is loop_fut:
                loop = loop_fut.result()
                try:
                    yield loop
                finally:
                    loop.call_soon_threadsafe(stop_event.set)
            else:
                fut.result()

# Create a loop in another thread
with loop_in_thread() as loop:
    # Create a coroutine
    coro = asyncio.sleep(1, result=3)

    # Submit the coroutine to a given loop
    future = asyncio.run_coroutine_threadsafe(coro, loop)

    # Wait for the result with an optional timeout argument
    assert future.result(timeout=2) == 3

Wenn in der Koroutine eine Ausnahme ausgelöst wird, wird die zurückgegebene Future benachrichtigt. Sie kann auch verwendet werden, um die Aufgabe in der Event-Schleife abzubrechen.

try:
    result = future.result(timeout)
except TimeoutError:
    print('The coroutine took too long, cancelling the task...')
    future.cancel()
except Exception as exc:
    print(f'The coroutine raised an exception: {exc!r}')
else:
    print(f'The coroutine returned: {result!r}')

Siehe den Abschnitt Concurrency and Multithreading in der Dokumentation.

Im Gegensatz zu anderen asyncio-Funktionen erfordert diese Funktion, dass das Argument loop explizit übergeben wird.

Hinzugefügt in Version 3.5.1.

Introspektion

asyncio.current_task(loop=None)

Gibt die aktuell laufende Task-Instanz zurück oder None, wenn keine Aufgabe läuft.

Wenn loop None ist, wird get_running_loop() verwendet, um die aktuelle Schleife zu erhalten.

Hinzugefügt in Version 3.7.

asyncio.all_tasks(loop=None)

Gibt eine Menge von noch nicht abgeschlossenen Task-Objekten zurück, die von der Schleife ausgeführt werden.

Wenn loop None ist, wird get_running_loop() verwendet, um die aktuelle Schleife zu erhalten.

Hinzugefügt in Version 3.7.

asyncio.iscoroutine(obj)

Gibt True zurück, wenn obj ein Koroutinenobjekt ist.

Hinzugefügt in Version 3.4.

Task-Objekt

class asyncio.Task(coro, *, loop=None, name=None, context=None, eager_start=False)

Ein Future-ähnliches Objekt, das eine Python-Koroutine ausführt. Nicht thread-sicher.

Aufgaben werden verwendet, um Koroutinen in Event-Schleifen auszuführen. Wenn eine Koroutine auf eine Future wartet, pausiert die Aufgabe die Ausführung der Koroutine und wartet auf den Abschluss der Future. Wenn die Future fertig ist, wird die Ausführung der umwickelten Koroutine fortgesetzt.

Event-Schleifen verwenden kooperatives Scheduling: eine Event-Schleife führt jeweils eine Aufgabe aus. Während eine Aufgabe auf den Abschluss einer Future wartet, führt die Event-Schleife andere Aufgaben, Rückrufe aus oder führt E/A-Operationen durch.

Verwenden Sie die High-Level-Funktion asyncio.create_task() zum Erstellen von Tasks oder die Low-Level-Funktionen loop.create_task() oder ensure_future(). Die manuelle Instanziierung von Tasks wird nicht empfohlen.

Um eine laufende Aufgabe abzubrechen, verwenden Sie die Methode cancel(). Das Aufrufen dieser Methode bewirkt, dass die Aufgabe eine Ausnahme vom Typ CancelledError in die umwickelte Koroutine wirft. Wenn eine Koroutine während des Abbrechens auf ein Future-Objekt wartet, wird das Future-Objekt abgebrochen.

cancelled() kann verwendet werden, um zu überprüfen, ob die Aufgabe abgebrochen wurde. Die Methode gibt True zurück, wenn die umwickelte Koroutine die Ausnahme CancelledError nicht unterdrückt hat und tatsächlich abgebrochen wurde.

asyncio.Task erbt von Future alle seine APIs außer Future.set_result() und Future.set_exception().

Ein optionales Schlüsselwort-Argument context ermöglicht die Angabe eines benutzerdefinierten contextvars.Context für die Ausführung von coro. Wenn kein context bereitgestellt wird, kopiert die Aufgabe den aktuellen Kontext und führt ihre Koroutine später im kopierten Kontext aus.

Ein optionales Schlüsselwort-Argument eager_start ermöglicht das sofortige Starten der Ausführung der asyncio.Task zum Zeitpunkt der Task-Erstellung. Wenn es auf True gesetzt ist und die Event-Schleife läuft, beginnt die Aufgabe sofort mit der Ausführung der Koroutine, bis zum ersten Mal, an dem die Koroutine blockiert. Wenn die Koroutine ohne Blockieren zurückkehrt oder eine Ausnahme auslöst, ist die Aufgabe sofort beendet und überspringt die Planung zur Event-Schleife.

Geändert in Version 3.7: Unterstützung für das Modul contextvars hinzugefügt.

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

Veraltet seit Version 3.10: Eine Deprecation-Warnung wird ausgegeben, wenn loop nicht angegeben ist und keine laufende Event-Schleife vorhanden ist.

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

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

done()

Gibt True zurück, wenn die Aufgabe fertig ist.

Eine Aufgabe ist fertig, wenn die umwickelte Koroutine entweder einen Wert zurückgegeben, eine Ausnahme ausgelöst oder die Aufgabe abgebrochen wurde.

result()

Gibt das Ergebnis der Aufgabe zurück.

Wenn die Aufgabe fertig ist, wird das Ergebnis der umwickelten Koroutine zurückgegeben (oder wenn die Koroutine eine Ausnahme ausgelöst hat, wird diese Ausnahme erneut ausgelöst).

Wenn die Aufgabe abgebrochen wurde, löst diese Methode eine Ausnahme vom Typ CancelledError aus.

Wenn das Ergebnis der Aufgabe noch nicht verfügbar ist, löst diese Methode eine Ausnahme vom Typ InvalidStateError aus.

exception()

Gibt die Ausnahme der Aufgabe zurück.

Wenn die umschlossene Koroutine eine Ausnahme ausgelöst hat, wird diese Ausnahme zurückgegeben. Wenn die umschlossene Koroutine normal zurückgegeben hat, gibt diese Methode None zurück.

Wenn die Aufgabe abgebrochen wurde, löst diese Methode eine Ausnahme vom Typ CancelledError aus.

Wenn der Task noch nicht erledigt ist, löst diese Methode eine InvalidStateError Ausnahme aus.

add_done_callback(callback, *, context=None)

Fügt einen Callback hinzu, der ausgeführt werden soll, wenn der Task erledigt ist.

Diese Methode sollte nur in Low-Level-Callback-basiertem Code verwendet werden.

Weitere Details finden Sie in der Dokumentation von Future.add_done_callback().

remove_done_callback(callback)

Entfernt callback aus der Callback-Liste.

Diese Methode sollte nur in Low-Level-Callback-basiertem Code verwendet werden.

Weitere Details finden Sie in der Dokumentation von Future.remove_done_callback().

get_stack(*, limit=None)

Gibt die Liste der Stack-Frames für diesen Task zurück.

Wenn die umschlossene Koroutine noch nicht erledigt ist, wird der Stack zurückgegeben, an dem sie unterbrochen ist. Wenn die Koroutine erfolgreich abgeschlossen oder abgebrochen wurde, gibt dies eine leere Liste zurück. Wenn die Koroutine durch eine Ausnahme beendet wurde, gibt dies die Liste der Traceback-Frames zurück.

Die Frames sind immer von ältesten zu neuesten sortiert.

Für eine unterbrochene Koroutine wird nur ein Stack-Frame zurückgegeben.

Das optionale Argument limit legt die maximale Anzahl zurückzugebender Frames fest; standardmäßig werden alle verfügbaren Frames zurückgegeben. Die Reihenfolge der zurückgegebenen Liste unterscheidet sich je nachdem, ob ein Stack oder ein Traceback zurückgegeben wird: die neuesten Frames eines Stacks werden zurückgegeben, aber die ältesten Frames eines Tracebacks werden zurückgegeben. (Dies entspricht dem Verhalten des traceback-Moduls.)

print_stack(*, limit=None, file=None)

Gibt den Stack oder Traceback für diesen Task aus.

Dies erzeugt eine Ausgabe, die der des traceback-Moduls für die von get_stack() abgerufenen Frames ähnelt.

Das Argument limit wird direkt an get_stack() übergeben.

Das Argument file ist ein I/O-Stream, in den die Ausgabe geschrieben wird; standardmäßig wird die Ausgabe nach sys.stdout geschrieben.

get_coro()

Gibt das von der Task umschlossene Koroutine-Objekt zurück.

Hinweis

Dies gibt None für Tasks zurück, die bereits eifrig abgeschlossen wurden. Siehe Eager Task Factory.

Hinzugefügt in Version 3.8.

Geändert in Version 3.12: Die neu hinzugefügte eifrige Task-Ausführung bedeutet, dass das Ergebnis None sein kann.

get_context()

Gibt das mit dem Task assoziierte contextvars.Context-Objekt zurück.

Hinzugefügt in Version 3.12.

get_name()

Gibt den Namen des Tasks zurück.

Wenn dem Task kein Name explizit zugewiesen wurde, generiert die Standardimplementierung von asyncio Task während der Instanziierung einen Standardnamen.

Hinzugefügt in Version 3.8.

set_name(value)

Setzt den Namen des Tasks.

Das Argument value kann jedes Objekt sein, das dann in einen String konvertiert wird.

In der Standardimplementierung von Task ist der Name in der repr()-Ausgabe eines Task-Objekts sichtbar.

Hinzugefügt in Version 3.8.

cancel(msg=None)

Fordert die Abbrechung des Tasks an.

Wenn der Task bereits erledigt oder abgebrochen ist, gibt False zurück, ansonsten True.

Die Methode veranlasst, dass eine CancelledError Ausnahme in der nächsten Schleife der Event-Schleife in die umschlossene Koroutine geworfen wird.

Die Koroutine hat dann die Möglichkeit, aufzuräumen oder die Anforderung sogar abzulehnen, indem sie die Ausnahme mit einem try … … except CancelledErrorfinally Block unterdrückt. Daher garantiert Task.cancel() im Gegensatz zu Future.cancel() nicht, dass der Task abgebrochen wird, obwohl die Unterdrückung des Abbruchs nicht üblich ist und aktiv davon abgeraten wird. Sollte sich die Koroutine dennoch entscheiden, den Abbruch zu unterdrücken, muss sie zusätzlich zur Behandlung der Ausnahme Task.uncancel() aufrufen.

Geändert in Version 3.9: Der Parameter msg wurde hinzugefügt.

Geändert in Version 3.11: Der Parameter msg wird vom abgebrochenen Task an seinen Waiter weitergegeben.

Das folgende Beispiel zeigt, wie Koroutinen die Abbruchsanforderung abfangen können

async def cancel_me():
    print('cancel_me(): before sleep')

    try:
        # Wait for 1 hour
        await asyncio.sleep(3600)
    except asyncio.CancelledError:
        print('cancel_me(): cancel sleep')
        raise
    finally:
        print('cancel_me(): after sleep')

async def main():
    # Create a "cancel_me" Task
    task = asyncio.create_task(cancel_me())

    # Wait for 1 second
    await asyncio.sleep(1)

    task.cancel()
    try:
        await task
    except asyncio.CancelledError:
        print("main(): cancel_me is cancelled now")

asyncio.run(main())

# Expected output:
#
#     cancel_me(): before sleep
#     cancel_me(): cancel sleep
#     cancel_me(): after sleep
#     main(): cancel_me is cancelled now
cancelled()

Gibt True zurück, wenn der Task abgebrochen ist.

Der Task ist abgebrochen, wenn der Abbruch mit cancel() angefordert wurde und die umschlossene Koroutine die hineingeworfene CancelledError Ausnahme weitergegeben hat.

uncancel()

Dekrementiert die Anzahl der Abbruchanforderungen an diesen Task.

Gibt die verbleibende Anzahl von Abbruchanforderungen zurück.

Beachten Sie, dass nach Abschluss der Ausführung eines abgebrochenen Tasks weitere Aufrufe von uncancel() unwirksam sind.

Hinzugefügt in Version 3.11.

Diese Methode wird von den internen asyncio-Mechanismen verwendet und ist nicht für die Verwendung durch Endbenutzer gedacht. Insbesondere wenn ein Task erfolgreich wieder aufgerufen wird, ermöglicht dies, dass strukturierte Nebenläufigkeitskonstrukte wie Task Groups und asyncio.timeout() weiterlaufen und den Abbruch auf den jeweiligen strukturierten Block beschränken. Zum Beispiel

async def make_request_with_timeout():
    try:
        async with asyncio.timeout(1):
            # Structured block affected by the timeout:
            await make_request()
            await make_another_request()
    except TimeoutError:
        log("There was a timeout")
    # Outer code not affected by the timeout:
    await unrelated_code()

Während der Block mit make_request() und make_another_request() aufgrund des Timeouts abgebrochen werden könnte, sollte unrelated_code() auch im Falle eines Timeouts weiterlaufen. Dies wird mit uncancel() implementiert. TaskGroup Kontextmanager verwenden uncancel() auf ähnliche Weise.

Wenn Endbenutzercode aus irgendeinem Grund den Abbruch unterdrückt, indem er CancelledError abfängt, muss er diese Methode aufrufen, um den Abbruchszustand zu entfernen.

Wenn diese Methode die Abbruchszahl auf Null dekrementiert, prüft die Methode, ob ein vorheriger Aufruf von cancel() veranlasst hat, dass CancelledError in den Task geworfen wird. Wenn dies noch nicht geschehen ist, wird diese Anordnung rückgängig gemacht (durch Zurücksetzen des internen Flags _must_cancel).

Geändert in Version 3.13: Geändert, um ausstehende Abbruchanforderungen beim Erreichen von Null zurückzuziehen.

cancelling()

Gibt die Anzahl der ausstehenden Abbruchanforderungen an diesen Task zurück, d.h. die Anzahl der Aufrufe von cancel() abzüglich der Anzahl der Aufrufe von uncancel().

Beachten Sie, dass diese Zahl, wenn sie größer als Null ist, der Task aber noch ausgeführt wird, cancelled() immer noch False zurückgibt. Dies liegt daran, dass diese Zahl durch Aufrufe von uncancel() reduziert werden kann, was dazu führen kann, dass der Task nicht abgebrochen wird, wenn die Abbruchanforderungen auf Null sinken.

Diese Methode wird von den internen asyncio-Mechanismen verwendet und ist nicht für die Verwendung durch Endbenutzer gedacht. Siehe uncancel() für weitere Details.

Hinzugefügt in Version 3.11.