我目前正在使用Python Flask创建一个网络应用程序,而且我遇到了障碍,我不确定我是否正确地思考它。
因此,我的网站主页只是一个简单的目标网页,其中包含执行网站功能所需的文字输入。我想要实现的是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")
由于调查并不依赖于用户输入,而是让用户坐在加载屏幕上,我希望他们能够在功能在后台运行时启动调查,这是可能的,我该怎么做?
答案 0 :(得分:7)
更新:我必须在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
上没有括号,因为我们不是正在运行它 - 函数是对象,所以我们将函数本身传递给{{ 1}}。至于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()
函数正在完成我们之前正在做的事情 - 它现在只是有点整洁了。您可以在任何路径中调用它,而无需重新编写线程逻辑。你会注意到这个函数实际上返回了线程 - 对于这个例子,我们不需要需要,但是稍后你可能想要对该线程做些其他事情,所以返回它会使线程产生如果您需要,可以使用该对象。