Django View中的Python Asyncio

Jua*_*ano 12 python django

我想同时在Django视图上从API发出两个POST请求.

这就是我在django之外做的事情.

import asyncio
import speech_recognition as sr

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.get_even_loop()
loop.run_until_complete(main("en-US", "es-ES"))
Run Code Online (Sandbox Code Playgroud)

我对事件循环感到困惑.我如何在Django视图中执行此操作?我需要使用嵌套函数吗?

def ibmaudio_ibm(request, language1, language2):
     #Asyncio code here
Run Code Online (Sandbox Code Playgroud)

编辑:这甚至被认为是重复的?使用crontab进行并行调用和schedulling是完全不同的事情......

Jua*_*ano 15

解决方案是将函数嵌套在另一个函数中.

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)
Run Code Online (Sandbox Code Playgroud)

  • @Juanvulcano它运行得更快,因为你同时运行异步请求.但是,`loop.run_until_complete(main(language1,language2))`阻止进一步执行,直到异步操作完成.这意味着django worker将无法满足其他请求,直到这个请求完成. (5认同)
  • 这仍然在Django请求响应周期中受阻 (2认同)

Bob*_*Bob 6

在这种特殊情况下,您可以简单地使用ThreadPoolExecutor,asyncio无论如何都在使用它.run_in_executor(但在您的示例中还添加了冗余的代码行/循环创建等).

from concurrent.futures import ThreadPoolExecutor, wait

# create the executor outisde of the view with the number of workers you may need
executor = ThreadPoolExecutor(max_workers=2)

def reco_ibm(lang):
    return(r.recognize_ibm(audio, key, secret language=str(lang), show_all=True))

def djangoview(request, language1, language2):
    r = sr.Recognizer()
    with sr.AudioFile(path.join(os.getcwd(), "audio.wav")) as source:
        audio = r.record(source)

        # then use it pretty trivially:
        futures = []
        for lang in [language1, language2]:
            futures.append(executor.submit(reco_ibm, lang)
        completed, pending = wait(futures)
        # `pending` will always be empty here (see the docs on wait)

        result1, result2 = [i.resut() for i in completed]

    # do whatever you want with results etc.
Run Code Online (Sandbox Code Playgroud)

请参阅https://docs.python.org/3/library/concurrent.futures.html