簡體   English   中英

如何在主循環中處理請求時從 django 視圖運行異步 function 以在后台運行?

[英]How can I run an async function from a django view to run in the background while I process requests in the main loop?

正如我在標題中所說,我希望在處理來自前端的請求時在后台運行一個任務來處理大型數據庫查詢。 我什至可以用 async/asyncio 做到這一點嗎? 我被告知這是可能的...

出於上下文的目的,我想做類似以下的事情。 另請注意,我真的不需要 function 告訴我它何時完成(盡管我很想知道它是否可能),因為我只是檢查是否最終寫入了 .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 但對於一個不那么復雜的問題來說,這真的感覺有點過頭了。

  1. 您需要使用 aync 定義您的視圖aync 在您的情況下,它應該是: async def post_data_view(request):
  2. 在您的異步視圖中 function:首先需要獲取循環。 然后在循環中創建一個任務。 它應該是:
    async def post_data_view(request):
        if request.method == 'POST':
        ....
        loop = asyncio.get_event_loop()
        loop.create_task(do_long_query_in_the_background(some_data))
        return HttpResponse('Received. Ask me in a while if I finished.')
async def f():
    while True:
        print(0)
        await asyncio.sleep(2)

asyncio.run(f())

asyncio 的run方法設置您的事件循環並創建Task object,安排它運行並等待它完成,然后再執行任何其他代碼。

雖然看起來很簡單,但異步編程需要一種非常不同的編程方法,因為事情可以按任何順序發生,您必須非常仔細地考慮什么順序對函數的完成很重要。

不過,對於您的用例,您可能可以使用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...')



暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM