Aktualisieren:
Ersetzen Sie asyncio.ensure_future
durch asyncio.create_task
überall, wenn Sie Python verwenden> = 3.7 Es ist eine neuere, schönere Möglichkeit , Aufgaben zu erzeugen .
asyncio.Task zu "feuern und vergessen"
Laut Python-Dokumenten asyncio.Task
ist es möglich, eine Coroutine zu starten, um "im Hintergrund" auszuführen . Die von der asyncio.ensure_future
Funktion erstellte Aufgabe blockiert die Ausführung nicht (daher kehrt die Funktion sofort zurück!). Dies scheint eine Möglichkeit zu sein, wie gewünscht zu „feuern und zu vergessen“.
import asyncio
async def async_foo():
print("async_foo started")
await asyncio.sleep(1)
print("async_foo done")
async def main():
asyncio.ensure_future(async_foo()) # fire and forget async_foo()
# btw, you can also create tasks inside non-async funcs
print('Do some actions 1')
await asyncio.sleep(1)
print('Do some actions 2')
await asyncio.sleep(1)
print('Do some actions 3')
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Ausgabe:
Do some actions 1
async_foo started
Do some actions 2
async_foo done
Do some actions 3
Was ist, wenn Aufgaben nach Abschluss der Ereignisschleife ausgeführt werden?
Beachten Sie, dass Asyncio erwartet, dass die Aufgabe zum Zeitpunkt des Abschlusses der Ereignisschleife abgeschlossen ist. Wenn Sie also wechseln main()
zu:
async def main():
asyncio.ensure_future(async_foo()) # fire and forget
print('Do some actions 1')
await asyncio.sleep(0.1)
print('Do some actions 2')
Sie erhalten diese Warnung, nachdem das Programm beendet wurde:
Task was destroyed but it is pending!
task: <Task pending coro=<async_foo() running at [...]
Um zu verhindern, dass Sie nach Abschluss der Ereignisschleife einfach auf alle ausstehenden Aufgaben warten können :
async def main():
asyncio.ensure_future(async_foo()) # fire and forget
print('Do some actions 1')
await asyncio.sleep(0.1)
print('Do some actions 2')
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
# Let's also finish all running tasks:
pending = asyncio.Task.all_tasks()
loop.run_until_complete(asyncio.gather(*pending))
Töte Aufgaben, anstatt sie abzuwarten
Manchmal möchten Sie nicht darauf warten, dass Aufgaben erledigt werden (einige Aufgaben können beispielsweise so erstellt werden, dass sie für immer ausgeführt werden). In diesem Fall können Sie sie einfach abbrechen (), anstatt sie abzuwarten:
import asyncio
from contextlib import suppress
async def echo_forever():
while True:
print("echo")
await asyncio.sleep(1)
async def main():
asyncio.ensure_future(echo_forever()) # fire and forget
print('Do some actions 1')
await asyncio.sleep(1)
print('Do some actions 2')
await asyncio.sleep(1)
print('Do some actions 3')
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
# Let's also cancel all running tasks:
pending = asyncio.Task.all_tasks()
for task in pending:
task.cancel()
# Now we should await task to execute it's cancellation.
# Cancelled task raises asyncio.CancelledError that we can suppress:
with suppress(asyncio.CancelledError):
loop.run_until_complete(task)
Ausgabe:
Do some actions 1
echo
Do some actions 2
echo
Do some actions 3
echo