Introducing JupyterDash

Plotly
Plotly
Published in
7 min readMay 20, 2020

--

We’re excited to announce the release of JupyterDash, our new library that makes it easy to build Dash apps from Jupyter environments (e.g. classic Notebook, JupyterLab, Visual Studio Code notebooks, nteract, PyCharm notebooks, etc.).

Dash is Plotly’s open source Python (and R and Julia!) framework for building full stack analytic web applications using pure Python (no JavaScript required). Thanks to features like hot reloading and front-end error reporting provided by Dash DevTools, developers can quickly iterate on application designs using a traditional text editor or Integrated Development Environment (IDE). JupyterDash makes these features, and more, available from the Jupyter notebook.

tl;dr

To get started right away, install the jupyter-dash package using pip…

$ pip install jupyter-dash

or conda:

$ conda install -c conda-forge -c plotly jupyter-dash

Then, copy any Dash example into a Jupyter notebook cell and replace the dash.Dash class with the jupyter_dash.JupyterDash class. Or, copy and paste this example.

import plotly.express as px
from jupyter_dash import JupyterDash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
# Load Data
df = px.data.tips()
# Build App
app = JupyterDash(__name__)
app.layout = html.Div([
html.H1("JupyterDash Demo"),
dcc.Graph(id='graph'),
html.Label([
"colorscale",
dcc.Dropdown(
id='colorscale-dropdown', clearable=False,
value='plasma', options=[
{'label': c, 'value': c}
for c in px.colors.named_colorscales()
])
]),
])
# Define callback to update graph
@app.callback(
Output('graph', 'figure'),
[Input("colorscale-dropdown", "value")]
)
def update_figure(colorscale):
return px.scatter(
df, x="total_bill", y="tip", color="size",
color_continuous_scale=colorscale,
render_mode="webgl", title="Tips"
)
# Run app and display result inline in the notebook
app.run_server(mode='inline')
Dash apps & components can now display inline in Jupyter notebook and JupyterLab

You can also try it out, right in your browser, with binder.

JupyterDash features

Non-blocking execution

Dash for Python is built on Flask, and the Dash DevTools are built on the Flask development server. This server is intended to be run from a Python script and so, by design, it blocks the main Python thread while the server is running. While blocking, the server can watch the Python files that define the application and automatically reload the application when changes are detected.

While this is a great workflow when developing an application in a traditional text editor or IDE, it is not a good fit for Jupyter environments. In Jupyter environments, users expect to be able to iteratively execute code cells and then see the results of these changes automatically reflected in the display of the application. If running the server blocks the main thread, then it’s not possible to execute additional code cells without manually interrupting the execution of the kernel.

JupyterDash resolves this problem by executing the Flask development server in a background thread. This leaves the main execution thread available for additional calculations. When a request is made to serve a new version of the application on the same port, the currently running application is automatically shut down first. This makes is possible to quickly update a running application by simply re-executing the notebook cells that define it.

Display modes

JupyterDash supports three approaches to displaying a Dash application during interactive development. The display mode is configured using the mode argument to the JupyterDash.run_server method.

External: The default display mode is app.run_server(mode='external'). In this mode, the run_server method will print out the application’s URL. Most Jupyter environments will display this URL as a hyperlink that, when clicked, will open the application in a new browser tab. This is a great choice when you want to see exactly what your application will look like to an end-user.

External display mode

Inline: When the display mode is app.run_server(mode='inline'), run_server will use an IPython.display.IFrame to display the application inline in the notebook. This is a great choice for quickly iterating on small applications.

Inline display mode

JupyterLab: The JupyterLab extension for JupyterDash (jupyterlab-dash) provides a third display mode called app.run_server(mode='jupyterlab'). In this mode, run_server will display the application in a separate tab right in JupyterLab. This tab can then be arranged within the JupyterLab interface like any other tab. This is a great choice for quickly iterating on applications because it allows you to see the code and application side-by side.

JupyterLab display mode

Hot Reloading

Hot Reloading refers to the ability to automatically update a running web application when changes are made to the application’s code. The standard hot reload support provided by Dash DevTools doesn’t work in the Jupyter Notebook because the Flask development server doesn’t support watching for changes in a notebook.

In the inline display mode, no special support for hot reloading is needed because the application’s display is automatically regenerated each time run_server is called. In jupyterlab mode, hot reloading is implemented by having the JupyterLab extension automatically refresh the display of the application each time run_server is called. In external mode, JupyterDash makes use of a portion of the traditional Dash DevTools to have the application periodically poll the server for updates. When an update is detected due to a new call to run_server, the application is refreshed.

Hot Reload in JupyterLab display mode

Error Reporting

Dash DevTools provides a small user interface to display errors that result from property validation failures and exceptions raised inside callbacks. The notifications for property validation failures work from the Jupyter notebook as is, but supporting general callback exception notifications required some customization. Dash DevTools currently relies on the Flask development server to generate rich HTML representations of callback exception tracebacks.

Standard DevTools traceback

Unfortunately, this approach does not support code executed in a Jupyter notebook. JupyterDash leverages IPython’s built-in support for generating rich ANSI-colored stack traces, and then converts these to HTML for display in the Dash DevTools user interface using the ansi2html library. To make it easier to understand the cause of a callback exception, the values of function arguments and local variables at the time of the exception are included in the stack trace.

JupyterDash traceback

Jupyter Proxy Detection

When the Jupyter Server Proxy library is installed, JupyterDash can automatically route the application through the proxy. Proxy detection is performed by the JupyterDash.infer_jupyter_proxy_config() function.

This makes it easy to use JupyterDash in JupyterHub and binder configurations. Try it out using the binder link in the JupyterDash README.

Production Deployment

When used in a traditional (non-Jupyter) Python environment, JuypterDash will disable all development features. This makes it possible to convert a notebook using JupyterDash into a Python script and then deploy the app using a production WSGI server like gunicorn.

A notebook can be converted to a script in JupyterLab using the File >Export Notebook As… > Executable Script menu entry. Or, Jupytext can be used to pair a notebook with a Python script (using either the Jupytext light or percent formats). This way, it is possible to continue developing the application in the notebook and when notebook changes are saved, the changes will automatically be synchronized to the Python script.

Dash Enterprise Workspaces

JupyterDash is compatible with the Jupyter notebook support in the coming release of Dash Enterprise Workspaces. Stay tuned for more information!

JupyterDash in Dash Enterprise Workspaces

Give it a spin!

If this sounds interesting, please give it a try and let us know what you think on the Dash Community Forum.

Again, you can install the JupyterDash Python package using pip…

$ pip install jupyter-dash

or conda:

$ conda install -c conda-forge -c plotly jupyter-dash

If you’re working in JupyterLab, see the JupyterLab support section of the README for everything you need to know to get the JupyterLab extension up and running.

Learn More

--

--

Plotly
Plotly
Editor for

The low-code framework for rapidly building interactive, scalable data apps in Python.