在Django的View中使用asyncio的方法
起步
Django是个同步框架,本文并不是让Django变成异步框架。而是对于在一个view中需要请求多次httpapi的场景。
一个简单的例子
例子来源于 https://stackoverflow.com/questions/44667242/python-asyncio-in-django-view:
defdjangoview(request,language1,language2): asyncdefmain(language1,language2): loop=asyncio.get_event_loop() r=sr.Recognizer() withsr.AudioFile(path.join(os.getcwd(),"audio.wav"))assource: audio=r.record(source) defreco_ibm(lang): return(r.recognize_ibm(audio,key,secretlanguage=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=awaitfuture1 response2=awaitfuture2 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)
这个例子中,把两个任务放到 asyncio的loop运行,等到两个任务都完成了再返回 HttpResponse。
在Django的View中使用asyncio
现在可以对于上面的例子做一个扩充,让它能更合理被使用。
对于使用 asyncio,我们通常会创建个子线程专门处理异步任务。
在 wsgi.py中创建一个单独线程并运行事件循环:
importasyncio importthreading ... application=get_wsgi_application() #创建子线程并等待 thread_loop=asyncio.new_event_loop() defstart_loop(loop): asyncio.set_event_loop(loop) loop.run_forever() t=threading.Thread(target=start_loop,args=(thread_loop,),daemon=True) t.start()
然后就是在view中动态向里面添加任务了:
asyncdeffetch(url): asyncwithaiohttp.ClientSession()assession: asyncwithsession.get(url)asresponse: text=awaitresponse.text() returntext defhello(request): fromyeezy_bot.wsgiimportthread_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() returnHttpResponse('')
asyncio.run_coroutine_threadsafe()返回是Future对象,因此可以通过 fut.result()获得任务的运行结果。这个方式也可以处理API请求中的数据依赖的先后顺序。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。