在AWS EC2上用Streamlit运行Dash仪表盘遇主线程信号错误求助
问题
我用Python 3.7.10开发了基于Dash和matplotlib的仪表盘,代码文件为index.py。尝试部署到AWS EC2实例时,已完成以下操作:
- 执行
chmod 400 web04-test.pem配置密钥文件权限 - 通过
ssh -i "web04-test.pem" ec2-user@ec2-43-206-106-106.ap-northeast-1.compute.amazonaws.com连接EC2实例 - 切换至root用户,执行系统更新并安装Git
- 克隆GitHub仓库:
git clone https://github.com/*****/web04-test.git - 进入项目目录后,通过pip安装dash、pandas、matplotlib、streamlit、networkx等依赖包
- 执行
python3 -m streamlit run index.py启动仪表盘
启动后出现如下错误:
ValueError: signal only works in main thread Traceback: File "/usr/local/lib/python3.7/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 563, in _run_script exec(code, module.__dict__) File "/home/ec2-user/web04-test/index.py", line 422, in <module> app.run_server(debug=True) File "/usr/local/lib/python3.7/site-packages/dash/dash.py", line 2133, in run_server self.run(*args, **kwargs) File "/usr/local/lib/python3.7/site-packages/dash/dash.py", line 1980, in run self.server.run(host=host, port=port, debug=debug, **flask_run_options) File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1188, in run run_simple(t.cast(str, host), port, self, **options) File "/usr/local/lib/python3.7/site-packages/werkzeug/serving.py", line 1095, in run_simple reloader_type=reloader_type, File "/usr/local/lib/python3.7/site-packages/werkzeug/_reloader.py", line 427, in run_with_reloader signal.signal(signal.SIGTERM, lambda *args: sys.exit(0)) File "/usr/lib64/python3.7/signal.py", line 47, in signal handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler))
index.py核心代码:
import dash import dash_html_components as html import dash_core_components as dcc from dash.dependencies import Input , Output, State import plotly.graph_objs as go import pandas as pd import datetime ... app = dash.Dash(__name__ ) app.layout = html.Div([...]) ... if __name__ =='__main__': app.run_server(debug=True)
请问如何修复该错误,正常显示仪表盘?
解决方案
核心原因
你错误地用Streamlit启动Dash应用,两者是独立的Web框架,混用会导致线程冲突:Dash的run_server(debug=True)会启动Flask的调试重载器,而Streamlit本身运行在非主线程中,重载器尝试注册信号处理时就会触发signal only works in main thread错误。
修复步骤
修改启动方式与代码参数
放弃用Streamlit启动,直接用Python运行Dash应用,并调整run_server参数:- 修改
index.py中的启动代码:if __name__ =='__main__': app.run_server(debug=False, host='0.0.0.0', port=8050)host='0.0.0.0':允许EC2外部访问debug=False:禁用调试重载器,彻底避免线程信号问题(生产环境必须关闭调试模式)port=8050:Dash默认端口,可按需修改
- 在EC2终端执行启动命令:
python3 index.py
- 修改
配置EC2安全组
在AWS控制台的EC2实例安全组中添加入站规则:- 类型:自定义TCP
- 端口范围:8050(或你设置的端口)
- 源:可设为
0.0.0.0/0(允许所有IP访问),或限制为你的本地IP提升安全性
验证访问
启动应用后,通过EC2公网IP访问:http://ec2-43-206-106-106.ap-northeast-1.compute.amazonaws.com:8050
额外建议
- 如果要使用Streamlit部署,需重构代码为Streamlit风格,而非直接运行Dash应用
- 生产环境建议用Gunicorn或uWSGI等WSGI服务器托管Dash应用,替代直接用
run_server:
其中gunicorn -w 4 -b 0.0.0.0:8050 index:serverindex:server指index.py中的app.server对象(Dash基于Flask,app.server是底层Flask实例)
内容的提问来源于stack exchange,提问作者Anna
相关产品推荐
相关产品推荐

