The method of using asyncio in View of Django

  • 2021-07-16 02:45:24
  • OfStack

Start

Django is a synchronous framework, and this article does not make Django an asynchronous framework. But for scenarios where http and api need to be requested multiple times in one view.

1 Simple example

Examples are from https://stackoverflow.com/questions/44667242/python-asyncio-in-django-view:


def djangoview(request, language1, language2):
 async def main(language1, language2):
  loop = asyncio.get_event_loop()
  r = sr.Recognizer()
  with sr.AudioFile(path.join(os.getcwd(), "audio.wav")) as source:
   audio = r.record(source)
  def reco_ibm(lang):
   return(r.recognize_ibm(audio, key, secret language=lang, show_all=True))
  future1 = loop.run_in_executor(None, reco_ibm, str(language1))
  future2 = loop.run_in_executor(None, reco_ibm, str(language2))
  response1 = await future1
  response2 = await future2
 loop = asyncio.new_event_loop()
 asyncio.set_event_loop(loop)
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main(language1, language2))
 loop.close()
 return(HttpResponse)

In this example, put both tasks into loop of asyncio and wait until both tasks are complete before returning to HttpResponse.

Using asyncio in View of Django

Now we can make an extension to the above example, so that it can be used more reasonably.

With asyncio, we usually create child threads to handle asynchronous tasks.

Create a single thread in wsgi. py and run the event loop:


import asyncio
import threading

...
application = get_wsgi_application()

#  Create child threads and wait 
thread_loop = asyncio.new_event_loop()
def start_loop(loop):
 asyncio.set_event_loop(loop)
 loop.run_forever()

t = threading.Thread(target=start_loop, args=(thread_loop,), daemon=True)
t.start()

Then you dynamically add tasks to view:


async def fetch(url):
  async with aiohttp.ClientSession() as session:
   async with session.get(url) as response:
    text = await response.text()
    return text

def hello(request):
 from yeezy_bot.wsgi import thread_loop

 fut1 = asyncio.run_coroutine_threadsafe(fetch(url1), thread_loop)
 fut2 = asyncio.run_coroutine_threadsafe(fetch(url2), thread_loop)

 ret1 = fut1.result()
 ret2 = fut2.result()
 return HttpResponse('')

asyncio. run_coroutine_threadsafe () returns an Future object, so you can get the running result of the task through fut. result (). This method can also handle the sequence of data dependencies in API requests.


Related articles: