Dash点击按钮重复重载main.py:如何避免慢模块重复加载?
解决Dash背景回调导致模块重复加载的问题
问题场景
使用Dash背景回调实现进度条实时更新功能时,每次点击"Run Process"按钮,控制台都会多次打印"Importing slow utils",说明fake_utils模块被重复加载。该模块因读取大文件需要3分钟以上加载时间,重复加载严重影响性能,需保留进度条实时更新的同时解决此问题。
原因分析
Dash的DiskcacheManager为背景回调启动了多个工作进程,每个进程都会重新导入整个main.py脚本,包括顶层的fake_utils模块,导致重复加载。
解决方案
核心思路
将慢加载模块的导入逻辑放到工作进程初始化阶段,确保每个工作进程仅加载一次fake_utils,而非每次触发回调都重新导入。
修改后的代码
main.py
import dash_bootstrap_components as dbc from uuid import uuid4 import diskcache from dash import Dash, html, DiskcacheManager, Input, Output # 工作进程初始化函数:每个进程启动时仅执行一次 def init_worker(): global foo from fake_utils import foo launch_uid = uuid4() cache = diskcache.Cache("./cache") # 配置背景回调管理器,指定进程初始化函数 background_callback_manager = DiskcacheManager( cache, cache_by=[lambda: launch_uid], expire=60, worker_initializer=init_worker ) app = Dash(__name__, background_callback_manager=background_callback_manager, external_stylesheets=[dbc.themes.BOOTSTRAP]) app.layout = html.Div([ html.Button('Run Process', id='run-button'), dbc.Progress(id="progress-component", value=0, max=10), html.Div(id='output') ]) @app.callback( Output('output', 'children'), Input('run-button', 'n_clicks'), background=True, progress=[ Output("progress-component", "value"), Output("progress-component", "label"), ], ) def run_process(set_progress, n_clicks): if n_clicks is None: return html.Div() results = [] for i in range(10): res = foo() results.append(res) set_progress((i+1, f'{i+1}')) return 'Done' if __name__ == '__main__': # Debug模式下建议关闭自动重载,避免额外进程重复导入 app.run_server(debug=True, port=100, use_reloader=False)
fake_utils.py(保持不变)
import time print('Importing slow utils') def foo(): time.sleep(1) return 0
额外优化建议
- 缓存预加载数据:如果
fake_utils需要读取大文件,可在初始化函数中加载数据并存入diskcache,避免重复读取:def init_worker(): global foo from fake_utils import foo, load_large_file large_data = load_large_file() cache.set("preloaded_data", large_data) - 关闭Debug自动重载:Debug模式的自动重载会启动额外进程,设置
use_reloader=False可避免此问题,同时不影响断点调试。
内容的提问来源于stack exchange,提问作者david serero
相关产品推荐
相关产品推荐

