Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make a Python asyncio call from a Flask route

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) 
like image 615
user24502 Avatar asked Dec 16 '17 02:12

user24502


People also ask

Does Asyncio work with Flask?

Other event loops At the moment Flask only supports asyncio .

How do you call async function in Flask?

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 .

How do I make an asynchronous call in Python?

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.

Is Flask synchronous or asynchronous?

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.


1 Answers

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) 
like image 182
Travis Terry Avatar answered Sep 18 '22 11:09

Travis Terry