Aktuelle Infos:
Ab Python 3.7 wurde zu diesem Zweck eine asyncio.create_task(coro)
übergeordnete Funktion hinzugefügt .
Sie sollten es stattdessen auf andere Weise verwenden, um Aufgaben aus Coroutimes zu erstellen. Wenn Sie jedoch eine Aufgabe aus einer beliebigen Wartezeit erstellen müssen, sollten Sie diese verwenden asyncio.ensure_future(obj)
.
Alte Info:
ensure_future
vs. create_task
ensure_future
ist eine Methode zum Erstellen Task
aus coroutine
. Es erstellt Aufgaben auf unterschiedliche Weise basierend auf Argumenten (einschließlich der Verwendung von create_task
für Coroutinen und zukunftsähnliche Objekte).
create_task
ist eine abstrakte Methode von AbstractEventLoop
. Verschiedene Ereignisschleifen können diese Funktion auf unterschiedliche Weise implementieren.
Sie sollten verwenden ensure_future
, um Aufgaben zu erstellen. Sie benötigen create_task
nur, wenn Sie Ihren eigenen Ereignisschleifentyp implementieren möchten.
Aktualisieren:
@ bj0 zeigte auf Guidos Antwort zu diesem Thema:
Der Punkt ensure_future()
ist, wenn Sie etwas haben, das entweder eine Coroutine oder eine sein kann Future
(letztere enthält eine, Task
weil das eine Unterklasse von ist Future
), und Sie möchten eine Methode darauf aufrufen können, die nur für definiert ist Future
(wahrscheinlich die einzige nützliches Beispiel dafür cancel()
). Wenn es bereits ein Future
(oder Task
) ist, tut dies nichts; wenn es ein Koroutine ist es wickelt es in ein Task
.
Wenn Sie wissen, dass Sie eine Coroutine haben und diese geplant werden soll, ist die richtige API zu verwenden create_task()
. Das einzige Mal, wenn Sie anrufen sollten, ensure_future()
ist, wenn Sie eine API bereitstellen (wie die meisten von asyncios eigenen APIs), die entweder eine Coroutine oder eine akzeptiert, Future
und Sie müssen etwas tun, für das Sie eine benötigen Future
.
und später:
Letztendlich glaube ich immer noch, dass dies ensure_future()
ein angemessen dunkler Name für ein selten benötigtes Stück Funktionalität ist. Wenn Sie eine Aufgabe aus einer Coroutine erstellen, sollten Sie den entsprechend benannten verwenden
loop.create_task()
. Vielleicht sollte es dafür einen Alias geben
asyncio.create_task()
?
Es ist überraschend für mich. Meine Hauptmotivation ensure_future
war es, die Funktion auf höherer Ebene im Vergleich zum Mitglied der Schleife zu verwenden create_task
(die Diskussion enthält einige Ideen wie Hinzufügen asyncio.spawn
oder asyncio.create_task
).
Ich kann auch darauf hinweisen, dass es meiner Meinung nach ziemlich praktisch ist, eine universelle Funktion zu verwenden, die nur mit Awaitable
Coroutinen umgehen kann .
Guidos Antwort ist jedoch klar: "Wenn Sie eine Aufgabe aus einer Coroutine erstellen, sollten Sie den entsprechend benannten verwenden. loop.create_task()
"
Wann sollten Coroutinen in Aufgaben eingewickelt werden?
Coroutine in eine Aufgabe einwickeln - ist eine Möglichkeit, diese Coroutine "im Hintergrund" zu starten. Hier ist ein Beispiel:
import asyncio
async def msg(text):
await asyncio.sleep(0.1)
print(text)
async def long_operation():
print('long_operation started')
await asyncio.sleep(3)
print('long_operation finished')
async def main():
await msg('first')
# Now you want to start long_operation, but you don't want to wait it finised:
# long_operation should be started, but second msg should be printed immediately.
# Create task to do so:
task = asyncio.ensure_future(long_operation())
await msg('second')
# Now, when you want, you can await task finised:
await task
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Ausgabe:
first
long_operation started
second
long_operation finished
Sie können ersetzen, asyncio.ensure_future(long_operation())
nur await long_operation()
um den Unterschied zu spüren.
create_task
wenn Sie wirklich ein Aufgabenobjekt benötigen, das Sie normalerweise nicht benötigen sollten: github.com/python/asyncio/issues/477#issuecomment-268709555ensure_future
fügt automatisch die erstellt ,Task
um die Hauptereignisschleife?loop
Schlüsselwortarguments angeben ( siehe Signatur "sure_future" ).await
innerhalbmsg()
Kontrolle Ereignisschleife auf dem zweiten Gespräch zurückzukehren. Die Ereignisschleife kann nach dem Empfang der Steuerung gestartet werdenlong_operation()
. Es wurde demonstriert, wieensure_future
Coroutine gestartet wird, um gleichzeitig mit dem aktuellen Ausführungsfluss ausgeführt zu werden.create_task()
ensure_future()
create_task
,Wie Sie sehen können, ist die create_task spezifischer.
async
Funktion ohne create_task oder sure_futureDie einfache Aufruffunktion
async
gibt die Coroutine zurückUnd da das
gather
unter der Haube (ensure_future
) sicherstellt, dass Argumente Futures sind, ist dies explizitensure_future
überflüssig.Ähnliche Frage Was ist der Unterschied zwischen loop.create_task, asyncio.async / sure_future und Task?
quelle
Aus den offiziellen Dokumenten:
Detail:
Ab Python 3.7 gibt es also zwei Wrapper-Funktionen der obersten Ebene (ähnlich, aber unterschiedlich):
asyncio.create_task
: die einfachevent_loop.create_task(coro)
direkt anrufen . ( siehe Quellcode )ensure_future
die auch aufrufen,event_loop.create_task(coro)
wenn es sich um Coroutine handelt oder einfach nur, um sicherzustellen, dass der Rückgabetyp ein Asyncio ist . ( siehe Quellcode ). Wie auch immer,Task
ist immer noch eineFuture
aufgrund seiner Klassenvererbung ( ref ).Diese beiden Wrapper-Funktionen helfen Ihnen beim Aufrufen
BaseEventLoop.create_task
. Der einzige Unterschied besteht darinensure_future
, einawaitable
Objekt zu akzeptieren und es in eine Zukunft umzuwandeln. Außerdem können Sie Ihren eigenenevent_loop
Parameter in angebenensure_future
. Und je nachdem, ob Sie diese Funktionen benötigen oder nicht, können Sie einfach auswählen, welcher Wrapper verwendet werden soll.quelle
In Ihrem Beispiel werden alle drei Typen asynchron ausgeführt. Der einzige Unterschied besteht darin, dass Sie im dritten Beispiel alle 10 Coroutinen vorgeneriert und gemeinsam an die Schleife gesendet haben. so gibt nur der letzte zufällig Ausgabe aus.
quelle