diff --git a/dash/dash.py b/dash/dash.py index 44fad1efee..73e9060023 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -8,14 +8,16 @@ import pkgutil import warnings import re +import traceback from functools import wraps import plotly import dash_renderer import flask -from flask import Flask, Response +from flask import Flask, Response, got_request_exception from flask_compress import Compress +from flask_socketio import SocketIO from .dependencies import Event, Input, Output, State from .resources import Scripts, Css @@ -114,6 +116,7 @@ def __init__( self.index_string = index_string self._meta_tags = meta_tags or [] self._favicon = None + self._errors = "" if compress: # gzip @@ -760,4 +763,25 @@ def run_server(self, port=8050, debug=False, **flask_run_options): - self.server.run(port=port, debug=debug, **flask_run_options) + if debug: + socketio = SocketIO(self.server) + + @got_request_exception.connect_via(self.server) + # pylint: disable=unused-variable + def when_dash_gets_exception(server, exception, **extra): + socketio.emit( + 'error', + { + 'errorType': type(exception).__name__, + 'errorMessage': str(exception), + 'errorTraceback': traceback.format_exc(), + }, + namespace=( + '{}_dash-errors' + .format(self.config['routes_pathname_prefix']) + ) + ) + + socketio.run(self.server, port=port, debug=debug) + else: + self.server.run(port=port, debug=debug, **flask_run_options) diff --git a/dev-requirements.txt b/dev-requirements.txt index f667e354c3..1701b91b18 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -13,3 +13,4 @@ plotly>=2.0.8 requests[security] flake8 pylint==1.9.2 +Flask-SocketIO==3.0.1 diff --git a/requirements.txt b/requirements.txt index 4eb352abdc..2a7c86ab36 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,6 +10,7 @@ enum34==1.1.6 Flask==0.12 Flask-Compress==1.4.0 Flask-SeaSurf==0.2.2 +Flask-SocketIO==3.0.1 funcsigs==1.0.2 functools32==3.2.3.post2 ipdb==0.10.2