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-268709555