I want to execute an async function every time the Flask route is executed. Why is the abar
function never executed?
import asyncio from flask import Flask async def abar(a): print(a) loop = asyncio.get_event_loop() app = Flask(__name__) @app.route("/") def notify(): asyncio.ensure_future(abar("abar"), loop=loop) return "OK" if __name__ == "__main__": app.run(debug=False, use_reloader=False) loop.run_forever()
I also tried putting the blocking call in a separate thread. But it is still not calling the abar
function.
import asyncio from threading import Thread from flask import Flask async def abar(a): print(a) app = Flask(__name__) def start_worker(loop): asyncio.set_event_loop(loop) try: loop.run_forever() finally: loop.close() worker_loop = asyncio.new_event_loop() worker = Thread(target=start_worker, args=(worker_loop,)) @app.route("/") def notify(): asyncio.ensure_future(abar("abar"), loop=worker_loop) return "OK" if __name__ == "__main__": worker.start() app.run(debug=False, use_reloader=False)
Other event loops At the moment Flask only supports asyncio .
Flask 2.0 Async. Creating asynchronous routes is as simple as creating a synchronous route: You just need to install Flask with the extra async via pip install "Flask[async]" . Then, you can add the async keyword to your functions and use await .
To run an async function (coroutine) you have to call it using an Event Loop. Event Loops: You can think of Event Loop as functions to run asynchronous tasks and callbacks, perform network IO operations, and run subprocesses. Example 1: Event Loop example to run async Function to run a single async function: Python3.
After seeing what just happened, next time people say flask is synchronous and it can handle only one request at a time. Knowing that by configuring thread, process at app. run, you know for sure we will be able to handle more than a request at a time.
You can incorporate some async functionality into Flask apps without having to completely convert them to asyncio.
import asyncio from flask import Flask async def abar(a): print(a) loop = asyncio.get_event_loop() app = Flask(__name__) @app.route("/") def notify(): loop.run_until_complete(abar("abar")) return "OK" if __name__ == "__main__": app.run(debug=False, use_reloader=False)
This will block the Flask response until the async function returns, but it still allows you to do some clever things. I've used this pattern to perform many external requests in parallel using aiohttp, and then when they are complete, I'm back into traditional flask for data processing and template rendering.
import aiohttp import asyncio import async_timeout from flask import Flask loop = asyncio.get_event_loop() app = Flask(__name__) async def fetch(url): async with aiohttp.ClientSession() as session, async_timeout.timeout(10): async with session.get(url) as response: return await response.text() def fight(responses): return "Why can't we all just get along?" @app.route("/") def index(): # perform multiple async requests concurrently responses = loop.run_until_complete(asyncio.gather( fetch("https://google.com/"), fetch("https://bing.com/"), fetch("https://duckduckgo.com"), fetch("http://www.dogpile.com"), )) # do something with the results return fight(responses) if __name__ == "__main__": app.run(debug=False, use_reloader=False)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With