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

Flask与Dash集成部署PythonAnywhere时图表更新异常问题排查

问题根源

PythonAnywhere采用多worker进程部署,你的代码中使用**全局变量data**和直接修改dash_app.layout的方式,会导致不同worker进程间数据不共享:

  • 当Flask发送update-data请求时,只会更新当前处理该请求的worker的全局data和布局信号;
  • 用户访问Dash页面时,可能被分配到未更新的worker,导致读取旧数据或信号未触发回调;
  • 全局变量在多进程环境下无法保证会话隔离,不同用户的请求会互相干扰。
解决方案

1. 移除全局变量,基于Session ID动态读取数据

去掉Dash中的全局data变量,在回调中通过Flask Session获取当前用户的session_id,然后读取对应会话的数据文件:

def create_dash_app(flask_app):
    FONT_AWESOME = ["https://use.fontawesome.com/releases/v5.10.2/css/all.css"]
    dash_app = Dash(server=flask_app, url_base_pathname='/dashapp/', external_stylesheets=FONT_AWESOME)
    server = dash_app.server

    dash_app.layout = dbc.Container(children=[
        dcc.Store(id='data-update-signal', data=0),
        # ... 剩余布局代码 ...
    ])

    # 移除全局data变量

    @server.route('/update-data', methods=['POST'])
    def update_data():
        session_id = request.form.get('session_id')
        if not session_id:
            return "Session ID missing", 400
        # 仅确保数据文件已写入,无需修改Dash布局或全局变量
        return "Data updated", 200

    @dash_app.callback(
        Output('graph1', 'figure'),
        Output('graph3', 'figure'),
        Output('graph4', 'figure'),
        Input(ThemeSwitchAIO.ids.switch("theme"), "value"),
        Input('data-update-signal', 'data'),
        prevent_initial_call=False  # 页面加载时自动触发回调
    )
    def card1(toggle, data_update_signal):
        # 从Flask Session获取当前用户的session_id
        from flask import session
        session_id = session.get('session_id')
        if not session_id:
            return go.Figure(), go.Figure(), go.Figure()
        
        # 读取当前会话的数据文件
        data_path = os.path.join('uploads', session_id, 'temp_data.csv')
        if not os.path.exists(data_path):
            return go.Figure(), go.Figure(), go.Figure()
        
        data = pd.read_csv(data_path)

        template_theme1 = "flatly"
        template_theme2 = "darkly"
        template = template_theme1 if toggle else template_theme2

        # ... 图表生成代码 ...
        fig1 = go.Figure()
        # 基于data生成图表逻辑...

        fig3 = go.Figure()
        # ...

        fig4 = go.Figure()
        # ...

        return fig1, fig3, fig4

    return dash_app

2. 修正信号触发逻辑,避免直接修改布局

直接修改dash_app.layout的dcc.Store在多进程环境下无效,改为让Dash页面加载时自动触发回调:

  • 移除update-data中修改dash_app.layout.children[0].data的代码;
  • 通过prevent_initial_call=False确保页面首次加载时执行回调,读取当前session的数据;
  • 若需主动触发更新,可添加dcc.Interval组件定时检查数据,或在Flask跳转时携带参数触发。

3. 优化Flask跳转逻辑

确保Flask的session['session_id']能被Dash正确读取,使用相对路径避免跨域问题:

# Flask路由中修改redirect
return redirect("/dashapp/")

4. 清理临时文件(可选)

添加定时清理uploads目录下过期会话文件的逻辑,避免磁盘空间占用:

import shutil
import time

def clean_expired_sessions():
    upload_dir = 'uploads'
    if not os.path.exists(upload_dir):
        return
    for session_dir in os.listdir(upload_dir):
        dir_path = os.path.join(upload_dir, session_dir)
        if os.path.isdir(dir_path):
            # 删除7天前的会话目录
            if time.time() - os.path.getctime(dir_path) > 7*24*3600:
                shutil.rmtree(dir_path)

# 在Flask启动时调用,或用定时任务定期执行
clean_expired_sessions()
验证步骤
  1. 部署修改后的代码到PythonAnywhere;
  2. 上传数据后,检查Dash页面是否加载正确数据;
  3. 多次上传不同数据,确认图表不会出现混淆;
  4. 重启PythonAnywhere的web服务,验证会话隔离是否正常。

内容的提问来源于stack exchange,提问作者João Pandino

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 21:57:27