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

如何避免Dash重载器每次保存文件时重新执行数据库连接?

解决Dash重载器重复加载远程数据库的问题

问题背景

我在构建Dash仪表盘,启动时从Redshift远程数据库加载数据要花2分钟左右。开启use_reloader=True后,只要修改项目里任意.py文件(比如布局文件ventas.py、filtros.py),重载器就会重启整个进程,重新连接数据库加载数据。我想要的是修改布局后能实时看到变化,不用每次都重新连数据库。

最小复现示例

main.py

import os
import psycopg2
import pandas as pd
import dash
from dash import html

estado = {}

def cargar_datos():
    print("Connecting to DB...")  # 耗时约2分钟
    conn = psycopg2.connect(host="...", port=5439, database="...", user="...", password="...")
    estado["data"] = pd.read_sql("SELECT * FROM my_table", conn)
    conn.close()

cargar_datos()

app = dash.Dash(__name__)
app.layout = html.Div("hello")

if __name__ == "__main__":
    app.run(debug=True, use_reloader=True)

ventas.py

from dash import html
layout = html.Div("Ventas")

实际现象

每次保存ventas.py,终端都会打印Connecting to DB...,哪怕只是改了布局里的文字,也会重新走一遍数据库加载流程。

解决办法

方法1:利用环境变量控制仅首次加载数据

Dash基于Flask,重载器启动时会设置WERKZEUG_RUN_MAIN环境变量——主进程里这个值是false,重载后的子进程是true。我们可以用这个变量判断,只在主进程执行数据库加载,同时动态加载布局确保变更实时生效。

修改后的main.py:

import os
import psycopg2
import pandas as pd
import dash
from dash import html

estado = {}

def cargar_datos():
    print("Connecting to DB...")
    conn = psycopg2.connect(host="...", port=5439, database="...", user="...", password="...")
    estado["data"] = pd.read_sql("SELECT * FROM my_table", conn)
    conn.close()

# 只在主进程首次启动时加载数据
if os.environ.get("WERKZEUG_RUN_MAIN") != "true":
    cargar_datos()

app = dash.Dash(__name__)

# 动态导入布局文件,修改后能实时更新
def get_layout():
    from ventas import layout
    return layout

app.layout = get_layout

if __name__ == "__main__":
    app.run(debug=True, use_reloader=True)

方法2:用Flask缓存缓存数据库查询结果

引入flask_caching把查询结果缓存到本地,这样哪怕进程重启,也能直接读缓存,不用重新连数据库。

先装依赖:

pip install flask-caching

修改后的main.py:

import os
import psycopg2
import pandas as pd
import dash
from dash import html
from flask_caching import Cache

estado = {}

app = dash.Dash(__name__)

# 配置文件系统缓存,重启进程也能读取缓存
cache = Cache(app.server, config={
    'CACHE_TYPE': 'FileSystemCache',
    'CACHE_DIR': 'cache-directory',
    'CACHE_DEFAULT_TIMEOUT': 3600  # 缓存1小时,可按需调整
})

# 用缓存装饰器标记查询函数
@cache.memoize()
def cargar_datos():
    print("Connecting to DB...")
    conn = psycopg2.connect(host="...", port=5439, database="...", user="...", password="...")
    data = pd.read_sql("SELECT * FROM my_table", conn)
    conn.close()
    return data

# 首次加载后自动缓存
estado["data"] = cargar_datos()

# 动态加载布局
def get_layout():
    from ventas import layout
    return layout

app.layout = get_layout

if __name__ == "__main__":
    app.run(debug=True, use_reloader=True)

方法3:关闭全局重载,仅监听布局文件

如果不需要监听所有.py文件,直接关掉use_reloader,手动指定要监听的布局文件,Dash会在这些文件变更时更新布局,不会重启整个进程。

修改后的main.py:

import os
import psycopg2
import pandas as pd
import dash
from dash import html

estado = {}

def cargar_datos():
    print("Connecting to DB...")
    conn = psycopg2.connect(host="...", port=5439, database="...", user="...", password="...")
    estado["data"] = pd.read_sql("SELECT * FROM my_table", conn)
    conn.close()

cargar_datos()

app = dash.Dash(__name__)

def get_layout():
    from ventas import layout
    return layout

app.layout = get_layout

if __name__ == "__main__":
    # 指定要监听的布局文件
    extra_files = [
        os.path.join(os.getcwd(), "ventas.py"),
        os.path.join(os.getcwd(), "filtros.py")
    ]
    app.run(debug=True, use_reloader=False, extra_files=extra_files)

内容的提问来源于stack exchange,提问作者Francisco Augusto Varela Aguir

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 13:12:44