当我在主循环中处理请求时,如何从 django 视图运行异步函数以在后台运行?

Kvo*_*the 5 python django multithreading asynchronous

正如我在标题中所说,我希望在处理来自前端的请求时在后台运行一个任务来处理大型数据库查询。我什至可以使用 async/asyncio 来做到这一点吗?有人告诉我这是可能的...

出于上下文的目的,我想做如下的事情。另请注意,我实际上并不需要该函数告诉我何时完成(尽管我肯定想知道是否可能),因为我只是检查 .json 文件是否最终写入。


def post_data_view(request):
    if request.method == 'POST':
        ...
        do_long_query_in_the_background(some_data)
        return HttpResponse('Received. Ask me in a while if I finished.')

def is_it_done_view(request):
    if request.method == 'GET':
        data = find_json()
        if data:
            return JsonResponse(data)
        else:
            return HttpResponse('Not yet dude...')

async def do_long_query_in_the_background(data):
    # do some long processing...
    # dump the result to a result.json
    return
Run Code Online (Sandbox Code Playgroud)

有人告诉我这可以通过异步实现,但我真的很难理解。对于上下文,我试图简化这一点,即使如此,我发现我不太明白发生了什么:


async def f():
    while True:
        print(0)
        await asyncio.sleep(2)

asyncio.create_task(f())
Run Code Online (Sandbox Code Playgroud)

即使我尝试的这段代码也失败了sys:1: RuntimeWarning: coroutine 'f' was never awaited,但它确实可以在控制台上运行,我不明白为什么会这样。

我还想知道这对于线程来说是否可能并且安全?

我对此感到非常沮丧,因为其他线程中建议的一般解决方案似乎只是使用芹菜,但对于一个不那么复杂的问题来说,它确实感觉有点矫枉过正。

小智 1

import asyncio

async def f():
    while True:
        print(0)
        await asyncio.sleep(2)

asyncio.run(f())
Run Code Online (Sandbox Code Playgroud)

asyncio 中的方法run设置事件循环并创建Task对象,安排其运行并等待其完成,然后再执行任何其他代码。

虽然异步编程看起来很简单,但它需要一种非常不同的编程方法,因为事情可以按任何顺序发生,并且您必须非常仔细地考虑什么顺序对于完成函数很重要。

不过,对于您的用例,您也许可以使用threading. 您也许可以创建一个新线程,让它在后台运行。由于线程之间的切换会造成性能损失,但如果大部分处理在服务器端完成,您的用户可能会获得更好的体验。

#this runs forever as your loop never terminates
from threading import Thread
from time import sleep

def f():
    while True:
        print(0)
        await asyncio.sleep(2)

def main():
     print('starting new thread...')
     t = Thread(target=f)
     t.start()
     print('continuing other tasks...')
     sleep(5)
     print('still more things to do...')
Run Code Online (Sandbox Code Playgroud)