簡體   English   中英

Python Flask在同時執行函數的同時返回html頁面

[英]Python Flask returning a html page while simultaneously performing a function

我目前正在使用Python Flask創建一個Web應用程序,我遇到了障礙,我不確定我是否正確地考慮它。

因此,我網站的主頁只是一個簡單的登錄頁面,其中包含執行網站功能所需的文本輸入。 我想要實現的是Web應用程序在輸入文本后執行兩項操作。 首先,服務器獲取用戶名輸入並執行一個不向用戶返回任何內容的函數,但會創建一堆數據,這些數據將記錄到sqlite數據庫中,並在稍后的過程中使用。 然后,服務器返回在輸入用戶名后必須進行的調查的網頁。 但是,服務器執行的功能可能需要2分鍾以上,具體取決於用戶。 我目前對其編碼的方式,服務器執行該功能,然后一旦完成,它返回網頁,因此用戶卡在加載屏幕上最多2分鍾。

@app.route("/survey")
def main(raw_user):
    raw_user = request.args.get("SteamID")      <
    games = createGameDict(user_obj)            <----- the function
    tag_lst = get_tags(games)                   <
    return render_template("survey_page.html")

由於調查不依賴於用戶輸入,而是讓用戶坐在加載屏幕上,我希望他們能夠在功能在后台運行時啟動調查,這是可能的,我將如何去做?

更新:我必須在Flask中多次解決這個問題,所以我寫了一個名為Flask-Executor的小型Flask擴展程序來為我完成。 它是concurrent.futures的包裝器,提供了一些方便的功能,是我處理不需要在Flask中分發的后台任務的首選方式。


對於更復雜的背景任務,像芹菜這樣的東西是你最好的選擇。 但是,對於更簡單的用例,您需要的是threading模塊。

請考慮以下示例:

from flask import Flask
from time import sleep

app = Flask(__name__)


def slow_function(some_object):
    sleep(5)
    print(some_object)

@app.route('/')
def index():
    some_object = 'This is a test'
    slow_function(some_object)
    return 'hello'

if __name__ == '__main__':
    app.run()

在這里,我們創建一個函數slow_function() ,它在返回之前會休眠五秒鍾。 當我們在路由函數中調用它時,它會阻止頁面加載。 運行該示例並在瀏覽器中點擊http://127.0.0.1:5000 ,您將看到該頁面在加載前等待五秒鍾,之后測試消息將打印在您的終端中。

我們想要做的是將slow_function()放在不同的線程上。 只需幾行代碼,我們就可以使用threading模塊將這個函數的執行分離到另一個線程上:

from flask import Flask
from time import sleep
from threading import Thread

app = Flask(__name__)


def slow_function(some_object):
    sleep(5)
    print(some_object)

@app.route('/')
def index():
    some_object = 'This is a test'
    thr = Thread(target=slow_function, args=[some_object])
    thr.start()
    return 'hello'

if __name__ == '__main__':
    app.run()

我們在這里做的很簡單。 我們正在創建一個新的Thread實例並向它傳遞兩件事: target ,我們想要運行的函數,以及args ,傳遞給目標函數的參數。 請注意, slow_function上沒有括號,因為我們沒有運行它 - 函數是對象,所以我們將函數本身傳遞給Thread 至於args ,這總是需要一個列表。 即使你只有一個參數,將它包裝在一個列表中,這樣args就能得到它所期望的。

隨着我們的線程准備就緒, thr.start()執行它。 在瀏覽器中運行此示例,您會注意到索引路由現在立即加載。 但等待另外五秒鍾,果然,測試信息將在您的終端中打印出來。

現在,我們可以在這里停下來 - 但至少在我看來,在路線本身內部實際擁有這個線程代碼有點麻煩。 如果您需要在另一個路徑或不同的上下文中調用此函數,該怎么辦? 最好將其分解為自己的功能。 您可以將線程行為作為慢速函數本身的一部分,或者您可以創建一個“包裝器”函數 - 您采用哪種方法很大程度上取決於您正在做什么以及您的需求是什么。

讓我們創建一個包裝函數,看看它是什么樣的:

from flask import Flask
from time import sleep
from threading import Thread

app = Flask(__name__)


def slow_function(some_object):
    sleep(5)
    print(some_object)

def async_slow_function(some_object):
    thr = Thread(target=slow_function, args=[some_object])
    thr.start()
    return thr

@app.route('/')
def index():
    some_object = 'This is a test'
    async_slow_function(some_object)
    return 'hello'

if __name__ == '__main__':
    app.run()

async_slow_function()函數正在完成我們之前正在做的事情 - 它現在只是有點整潔了。 您可以在任何路徑中調用它,而無需重新編寫線程邏輯。 你會發現,這個函數實際上返回線程-我們並不需要針對這個例子,但也有可能是您想用該線程以后做其他的事情,所以返回它使線程對象可用,如果你需要它。

暫無
暫無

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

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