What is the best method to have an asyncio event loop run in a Flask app?
My main.py looks like this:
if __name__ == '__main__':
try:
app.run(host='0.0.0.0', port=8000, debug=True)
except:
logging.critical('server: CRASHED: Got exception on main handler')
logging.critical(traceback.format_exc())
raise
To add the option of async tasks, I needed to create an event_loop
before running the app
, but even when stopping the app run, a background thread still hangs (observable in debugger)
if __name__ == '__main__':
try:
app.event_loop = asyncio.get_event_loop()
app.run(host='0.0.0.0', port=8000, debug=True)
except:
logging.critical('server: CRASHED: Got exception on main handler')
logging.critical(traceback.format_exc())
raise
finally:
app.event_loop.stop()
app.event_loop.run_until_complete(app.event_loop.shutdown_asyncgens())
app.event_loop.close()
And using the following to create async tasks:
def future_callback(fut):
if fut.exception():
logging.error(fut.exception())
def fire_and_forget(func, *args, **kwargs):
if callable(func):
future = app.event_loop.run_in_executor(None, func, *args, **kwargs)
future.add_done_callback(future_callback)
else:
raise TypeError('Task must be a callable')
The only solution I could find was to add exit()
at the end of the finally
block, but I don't think its the correct solution.