我在一个烧瓶中有这个web应用程序,我想在提交表单后执行一些ML和AI算法。我在Redis和rq的帮助下在后台运行ML和AI算法(因为我的应用程序由Heroku托管,他们有超时的事情,你必须在30秒内返回响应)。工作完成后,我想得到的图像算法(一些图表),并输出到一个网页上,但我不知道如何渲染一个工作职能的模板,并从flask应用程序导入的应用程序似乎不工作。你对如何解决这个问题有什么想法吗?
我的代码片段来自将作业排入队列的flask应用程序:
def upload():
from mlsalespred import run_model
file = request.files['file']
dffile = pd.read_csv(file)
job = q.enqueue(run_model, dffile)
return render_template("waiting.html")我的工作函数中的代码片段:
def run_model(dataFrame):
- - - - - - - - - - -
- - some ml stuff - -
- - - - - - - - - - -
return render_template("uploaded.html", sales_fig = sales_fig.decode('utf8'), diff_fig = diff_fig.decode('utf8'), pred_fig = pred_fig.decode('utf8') )提前感谢
发布于 2019-12-27 11:12:07
一个基本但可行的解决方案(要点)
您只需从将作业入队的路由重定向,然后让meta标记定期刷新该页面,即可完成此操作。首先导入所需的库:
from flask import Flask, redirect, url_for, render_template_string
app = Flask(__name__)
from time import sleep
from rq import Queue
from rq.job import Job
from redis import Redis设置rq相关连接,并定义要运行的函数:
r = Redis(host='redisserver')
q = Queue(connection=r)
def slow_func(data):
sleep(5)
return 'Processed %s' % (data,)然后定义一个可以每5秒刷新一次页面的模板:
template_str='''
{% if refresh %}
{% endif %}
{{result}}
'''我们还将使用flask创建一个helper函数来返回插入了变量的模板
render_template_string. 请注意,如果未提供刷新,则默认为False:
def get_template(data, refresh=False):
return render_template_string(template_str, result=data, refresh=refresh)现在创建一个将把我们的函数排入队列的路由,获取它的rq job-id,然后返回一个重定向到result用它来查看id.
这只接受URL字符串中的输入,但可以从任何地方获得:
@app.route('/process/')
def process(data):
job = q.enqueue(slow_func, data)
return redirect(url_for('result', id=job.id))现在让我们在rq.Job对象。这里的逻辑可以调整,因为这将导致所有值的页面刷新,除了"finished":
@app.route('/result/')
def result(id):
job = Job.fetch(id, connection=r)
status = job.get_status()
if status in ['queued', 'started', 'deferred', 'failed']:
return get_template(status, refresh=True)
elif status == 'finished':
result = job.result
# If this is a string, we can simply return it:
return get_template(result)如果状态为"finished" 然后 job.result
将包含slow_func,因此我们将其呈现在页面上。
这种方法的缺点是在等待作业完成时向服务器发出多个请求。元刷新标签可能有点非常规。如果您从Javascript发送更新请求,那么有以下几种方法
解决方案它可以每隔一段时间发送AJAX请求,尽管这会受到相同的多请求问题的困扰。
另一种方法是使用websockets,即SSE,在作业完成后立即将其结果流式传输到前端。
更新:2021年2月27日
我决定尝试一下SSE的方法,用工作状态更新前端。我学到了这一点rq具有对更新meta属性,通过导入rq.get_current_job在作业内部,然后可以在作业刷新后从外部访问。
请参阅以下演示代码:
一个带有进度条的基本示例(要点)

https://stackoverflow.com/questions/59490025
复制相似问题