You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask线程实现加载页后无法跳转至visualize.html问题排查

Flask线程训练模型无法渲染visualize.html的问题排查与解决

核心问题原因

  • 线程中的return render_template完全无效:原请求/inputs已经返回loading.html并结束了HTTP响应,后台线程的返回值不会被发送给客户端,客户端根本接收不到这个渲染结果。
  • HTTP请求是一次性响应:每个请求对应一个唯一的响应,后台线程脱离了原请求的上下文,无法直接触发客户端的页面跳转或渲染。

解决方案:前端轮询+状态存储

要实现训练完成后自动跳转到可视化页面,需要通过「状态存储+前端轮询」的方式,让客户端主动检查训练状态,完成后再请求可视化页面。

步骤1:添加训练状态存储

在Flask应用中添加全局状态(生产环境建议用Redis/数据库替代全局变量,避免多进程冲突):

# 全局变量存储训练状态与结果,生产环境请用Redis/数据库
training_state = {
    "completed": False,
    "plots": None,
    "error": None
}

步骤2:修改inputs路由,重置训练状态

@app.route("/inputs", methods=["POST"])
def inputs():
    file = request.files.get("dataset")
    algo = request.form.getlist("algo")
    
    if not file:
        return render_template("input_form.html", error="请上传CSV文件", algos=ALGO, selected_algo=algo)
    
    data = io.StringIO(file.stream.read().decode("UTF8"), newline=None)
    dataset = pd.read_csv(data)

    # 重置训练状态
    training_state["completed"] = False
    training_state["plots"] = None
    training_state["error"] = None

    train_thread = Thread(target=train_models, args=(app, algo, dataset))
    train_thread.start()

    return render_template("loading.html")

步骤3:修改train_models函数,更新训练状态

把原来的return render_template改成更新状态存储:

def train_models(app, algo, dataset):
    print("开始训练...")
    try:
        with app.app_context():
            plot_model = Gen_Plot()
            plots = dict()
            selected_algo = dict()

            for model in algo:
                # 你的模型训练逻辑
                # 示例:plots[model] = 生成的可视化数据

            # 训练完成后更新状态
            training_state["completed"] = True
            training_state["plots"] = plots
            print("训练完成,结果已存储")
    except Exception as e:
        training_state["error"] = str(e)
        training_state["completed"] = True
        print(f"训练失败:{e}")

步骤4:新增训练状态检查路由

供前端轮询调用:

@app.route("/training-status")
def training_status_check():
    return jsonify(training_state)

步骤5:修改loading.html,添加轮询逻辑

让页面主动检查训练状态,完成后跳转:

<!DOCTYPE html>
<html>
<head>
    <title>训练中</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
    <h1>模型训练进行中...</h1>
    <div id="status">加载中...</div>

    <script>
        // 每2秒查询一次训练状态
        const pollTimer = setInterval(() => {
            $.get("/training-status", function(data) {
                if (data.completed) {
                    clearInterval(pollTimer);
                    if (data.error) {
                        $("#status").html(`训练失败:${data.error}`);
                    } else {
                        // 跳转到可视化页面
                        window.location.href = "/visualize";
                    }
                } else {
                    $("#status").html("训练仍在进行...");
                }
            });
        }, 2000);
    </script>
</body>
</html>

步骤6:新增可视化页面路由

专门用来渲染训练结果:

@app.route("/visualize")
def visualize():
    if not training_state["completed"]:
        return redirect("/loading")  # 未完成则跳回加载页
    if training_state["error"]:
        return render_template("error.html", error=training_state["error"])
    return render_template("visualize.html", plots=training_state["plots"])

生产环境注意事项

  • 全局变量仅适用于单进程调试,生产环境请用Redis、Memcached或数据库存储训练状态与结果,避免多进程数据不一致。
  • 如果训练任务耗时极长,建议用Celery等专业任务队列替代线程,支持任务持久化、重试等功能。
  • 可根据训练时长调整轮询间隔,减少不必要的请求。

内容的提问来源于stack exchange,提问作者Varad Kelkar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 18:37:41