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

问题描述

正如我在标题中所说,我希望在处理来自前端的请求时在后台运行一个任务来处理大型数据库查询。我什至可以用 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

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


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

asyncio.create_task(f())

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

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

我对此感到非常沮丧,因为其他线程中建议的一般解决方案似乎只是使用 celery,但对于一个不那么复杂的问题,它真的感觉有点过头了。

标签: pythondjangomultithreadingasynchronous

解决方案


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

asyncio.run(f())

来自 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...')




推荐阅读