Eine Coroutine ist eine Generatorfunktion, die sowohl Werte liefern als auch Werte von außen akzeptieren kann. Der Vorteil der Verwendung einer Coroutine besteht darin, dass wir die Ausführung einer Funktion anhalten und später fortsetzen können. Im Falle eines Netzwerkbetriebs ist es sinnvoll, die Ausführung einer Funktion anzuhalten, während wir auf die Antwort warten. Wir können die Zeit nutzen, um einige andere Funktionen auszuführen.
Eine Zukunft ist wie die Promise
Objekte aus Javascript. Es ist wie ein Platzhalter für einen Wert, der in Zukunft materialisiert wird. In dem oben genannten Fall kann uns eine Funktion während des Wartens auf Netzwerk-E / A einen Container geben, ein Versprechen, dass der Container nach Abschluss des Vorgangs mit dem Wert gefüllt wird. Wir halten am zukünftigen Objekt fest und wenn es erfüllt ist, können wir eine Methode aufrufen, um das tatsächliche Ergebnis abzurufen.
Direkte Antwort: Sie brauchen nicht, ensure_future
wenn Sie die Ergebnisse nicht brauchen. Sie sind gut, wenn Sie die Ergebnisse benötigen oder Ausnahmen abrufen.
Zusätzliche Credits: Ich würde run_in_executor
eine Executor
Instanz auswählen und übergeben , um die Anzahl der maximalen Mitarbeiter zu steuern.
Erklärungen und Beispielcodes
Im ersten Beispiel verwenden Sie Coroutinen. Die wait
Funktion nimmt eine Reihe von Coroutinen und kombiniert sie miteinander. Wird wait()
beendet, wenn alle Coroutinen erschöpft sind (abgeschlossen / beendet, alle Werte zurückgegeben).
loop = get_event_loop() #
loop.run_until_complete(wait(coros))
Die run_until_complete
Methode würde sicherstellen, dass die Schleife aktiv ist, bis die Ausführung abgeschlossen ist. Bitte beachten Sie, dass Sie in diesem Fall nicht die Ergebnisse der asynchronen Ausführung erhalten.
Im zweiten Beispiel verwenden Sie die ensure_future
Funktion, um eine Coroutine zu verpacken und ein Task
Objekt zurückzugeben, das eine Art ist Future
. Die Coroutine soll beim Aufruf in der Hauptereignisschleife ausgeführt werden ensure_future
. Das zurückgegebene Future / Task-Objekt hat noch keinen Wert, aber im Laufe der Zeit, wenn die Netzwerkoperationen beendet sind, enthält das Future-Objekt das Ergebnis der Operation.
from asyncio import ensure_future
futures = []
for i in range(5):
futures.append(ensure_future(foo(i)))
loop = get_event_loop()
loop.run_until_complete(wait(futures))
In diesem Beispiel machen wir dasselbe, außer dass wir Futures verwenden, anstatt nur Coroutinen zu verwenden.
Schauen wir uns ein Beispiel für die Verwendung von Asyncio / Coroutines / Futures an:
import asyncio
async def slow_operation():
await asyncio.sleep(1)
return 'Future is done!'
def got_result(future):
print(future.result())
# We have result, so let's stop
loop.stop()
loop = asyncio.get_event_loop()
task = loop.create_task(slow_operation())
task.add_done_callback(got_result)
# We run forever
loop.run_forever()
Hier haben wir die create_task
Methode für das loop
Objekt verwendet. ensure_future
würde die Aufgabe in der Hauptereignisschleife planen. Diese Methode ermöglicht es uns, eine Coroutine in einer von uns ausgewählten Schleife zu planen.
Wir sehen auch das Konzept des Hinzufügens eines Rückrufs mithilfe der add_done_callback
Methode für das Task-Objekt.
A Task
ist, done
wenn die Coroutine einen Wert zurückgibt, eine Ausnahme auslöst oder abgebrochen wird. Es gibt Methoden, um diese Vorfälle zu überprüfen.
Ich habe einige Blog-Beiträge zu diesen Themen geschrieben, die helfen könnten:
Weitere Details finden Sie natürlich im offiziellen Handbuch: https://docs.python.org/3/library/asyncio.html
ensure_future()
? Und wenn ich das Ergebnis brauche, kann ich es nicht einfach verwendenrun_until_complete(gather(coros))
?