A veces hay alguna operación asincrónica no crítica que debe suceder, pero no quiero esperar a que se complete. En la implementación de corrutinas de Tornado, puede "disparar y olvidar" una función asincrónica simplemente omitiendo la yield
palabra clave.
He estado tratando de averiguar cómo "disparar y olvidar" con la nueva sintaxis async
/ await
lanzada en Python 3.5. Por ejemplo, un fragmento de código simplificado:
async def async_foo():
print("Do some stuff asynchronously here...")
def bar():
async_foo() # fire and forget "async_foo()"
bar()
Sin embargo, lo que sucede es que bar()
nunca se ejecuta y, en cambio, recibimos una advertencia de tiempo de ejecución:
RuntimeWarning: coroutine 'async_foo' was never awaited
async_foo() # fire and forget "async_foo()"
python
python-3.5
python-asyncio
Mike N
fuente
fuente
Respuestas:
Upd:
Reemplace
asyncio.ensure_future
con enasyncio.create_task
todas partes si está usando Python> = 3.7 Es una forma más nueva y agradable de generar tareas .asyncio. Tarea para "disparar y olvidar"
De acuerdo con los documentos de Python
asyncio.Task
, es posible iniciar algunas corrutinas para ejecutar "en segundo plano" . La tarea creada por laasyncio.ensure_future
función no bloqueará la ejecución (¡por lo tanto, la función regresará inmediatamente!). Esto parece una forma de "disparar y olvidar" como lo solicitó.Salida:
¿Qué sucede si las tareas se ejecutan después de que se completa el ciclo de eventos?
Tenga en cuenta que asyncio espera que la tarea se complete en el momento en que se complete el ciclo de eventos. Entonces, si cambia
main()
a:Recibirá esta advertencia después de que finalice el programa:
Para evitarlo, puede esperar todas las tareas pendientes una vez completado el ciclo de eventos:
Mata tareas en lugar de esperarlas
A veces, no desea esperar a que se realicen tareas (por ejemplo, es posible que algunas tareas se creen para ejecutarse para siempre). En ese caso, puede cancelarlos () en lugar de esperarlos:
Salida:
fuente
stop()
método.Gracias Sergey por la sucinta respuesta. Aquí está la versión decorada del mismo.
Produce
Nota: Verifique mi otra respuesta que hace lo mismo usando hilos simples.
fuente
Esta no es una ejecución completamente asincrónica, pero quizás run_in_executor () sea adecuado para usted.
fuente
executor
predeterminado para llamarconcurrent.futures.ThreadPoolExecutor.submit()
. Lo menciono porque crear hilos no es gratis; disparar y olvidar 1000 veces por segundo probablemente ejercerá una gran presión en la gestión de subprocesosPor alguna razón, si no puede usar
asyncio
, aquí está la implementación con subprocesos simples. Compruebe mis otras respuestas y la respuesta de Sergey también.fuente