Plotly Dash回调未触发,如何停止Python脚本执行?
Dash应用无法触发/shutdown回调的问题排查与解决
我遇到了和《How to stop execution after some time?》相同的需求,尝试了其中的Plotly Dash解决方案,但完全没效果——对应的回调代码根本没被执行到。
设置好app.layout后,我写了如下代码:
def shutdown(): func = request.environ.get('werkzeug.server.shutdown') if func is None: raise RuntimeError('Not running with the Werkzeug Server') func() @app.callback(dependencies.Output('page-content', 'children'), [dependencies.Input('url', 'pathname')]) def display_page(pathname): if pathname == '/shutdown': print('I\'m here') shutdown() return html.Div([html.H3('You are on page {}'.format(pathname))]) if __name__ == '__main__': app.title = "EOS Testing Dashboard" app.run_server(debug=False)
代码里的print('I\'m here')从未执行,甚至在最后一行加sys.exit()也没反应,请问这是什么原因?该如何解决?
问题原因
- 缺少关键组件配置:如果
app.layout里没加dcc.Location组件,或者组件参数不对,url的pathname输入根本不会触发回调,自然走不到/shutdown的判断逻辑。 - Werkzeug shutdown方法已废弃:新版本Werkzeug移除了
werkzeug.server.shutdown,就算回调触发了,调用这个方法会直接抛出异常,导致后续流程中断。 - 回调阻塞问题:就算shutdown方法还能用,调用它会直接终止服务器,导致回调无法完成返回值的传递,Dash可能会因为回调未正常返回而跳过部分代码执行。
解决方法
1. 先确保路由触发的基础配置正确
在app.layout里必须包含dcc.Location组件,并且设置refresh=False避免页面刷新打断回调:
import dash_core_components as dcc import dash_html_components as html app.layout = html.Div([ dcc.Location(id='url', refresh=False), html.Div(id='page-content') ])
配置完后访问http://localhost:8050/shutdown,回调才会被触发。
2. 替换废弃的shutdown方法,用线程异步停止服务器
改用app.server.shutdown(),并且通过线程异步执行,避免阻塞回调的返回流程:
import threading import time from dash import Dash, html, dcc, Input, Output app = Dash(__name__) app.layout = html.Div([ dcc.Location(id='url', refresh=False), html.Div(id='page-content') ]) def stop_server(): time.sleep(1) # 留时间让回调返回结果给前端 app.server.shutdown() @app.callback(Output('page-content', 'children'), Input('url', 'pathname')) def display_page(pathname): if pathname == '/shutdown': print("I'm here") # 开个线程执行停止操作,不阻塞当前回调 threading.Thread(target=stop_server).start() return html.Div([html.H3('Server is shutting down...')]) return html.Div([html.H3('You are on page {}'.format(pathname))]) if __name__ == '__main__': app.title = "EOS Testing Dashboard" app.run_server(debug=False)
3. 生产环境建议用外部管理方式
如果是生产环境部署,别在应用内部写shutdown逻辑,用Gunicorn、systemd这类进程管理工具,通过系统信号(比如Ctrl+C发送SIGINT)来启停服务器,更稳定可靠。
内容的提问来源于stack exchange,提问作者Anna Ramolini
相关产品推荐
相关产品推荐

