本文详解 flask 应用中使用线程执行耗时模型训练时,为何 render_template 在后台线程中无效,并提供基于全局缓存、会话标识与前端轮询的轻量级解决方案,避免引入 celery 等重型组件。
在 Flask 中,render_template() 只能在请求上下文(Request Context)内调用,且其返回值必须由当前请求处理函数(如 inputs())直接返回,才能被客户端接收并渲染。你代码中的关键问题在于:
- train_models() 在独立线程中运行,没有请求上下文(即使手动 with app.app_context(): 也仅支持数据库/配置访问,不支持响应生成);
- return render_template(“visualize.html”) 在线程中执行是完全无效的:它不会发送 HTTP 响应,也不会重定向浏览器,甚至可能因上下文缺失而抛出异常(取决于 Flask 版本);
- loading.html 虽被返回,但后续无机制通知前端“训练完成”,因此页面卡在加载状态。
✅ 正确思路是:分离“触发”与“获取结果”两个请求。主线程快速返回 loading.html,前端通过 AJAX 定期轮询后端接口,后端从共享存储中读取训练结果并返回数据或跳转指令。
✅ 推荐方案:内存缓存 + 轮询(零依赖、适合中小型应用)
我们使用 threading.local() 或全局字典(配合唯一任务 ID)暂存结果,并提供一个 /status/ 接口供前端查询。