Using with Jupyter¶
Working in Notebooks¶
Jupyter notebooks are computable documents often used for exploratory work, data analysis, teaching, and demonstration. A notebook is a series of input cells that can be individually executed to display their output immediately after the cell. In addition to Classic Notebooks there are also notebooks for the newer JupyterLab project. Bokeh can embed both standalone and Bokeh server content with either.
Standalone output¶
Standalone Bokeh content (i.e. that does not use a Bokeh server) can be embedded directly in classic Jupyter notebooks as well as in JupyterLab.
Classic Notebook¶
To display Bokeh plots inline in a classic Jupyter notebooks, use the
output_notebook()
function from bokeh.io instead of (or in addition to)
the output_file()
function we have seen previously. No other modifications
are required. When show()
is called, the plot will be displayed inline in
the next notebook output cell. You can see a Jupyter screenshot below:

Multiple plots can be displayed in a single notebook output cell by calling
show()
multiple times in the input cell. The plots will be displayed in order.

JupyterLab¶
In order to embed Bokeh plots inside of JupyterLab, you need to install the two JupyterLab extensions. First install jupyterlab-manager by running the following command:
jupyter labextension install @jupyter-widgets/jupyterlab-manager
And then similarly install the jupyter_bokeh extension:
jupyter labextension install @bokeh/jupyter_bokeh
Once this is installed, usage is the same as with classic notebooks above.

Bokeh Server Applications¶
It is also possible to embed full Bokeh server applications, that can connect plot events, and Bokeh’s built-in widgets, directly to Python callback code. See Running a Bokeh Server for general information about Bokeh server applications, and the following notebook for a complete example of a Bokeh application embedded in a Jupyter notebook:
JupyterHub¶
In order to embed Bokeh server applications when running notebooks from your own JupyterHub instance, some additional steps are necessary to enable network connectivity between the client browser and the Bokeh server running in the JupyterLab cell. This is because your browser needs to connect to the port the Bokeh server is listening on, but JupyterHub is acting as a reverse proxy between your browser and your JupyterLab container. Follow all the JupyterLab instructions above, then continue with the following steps below.
First, you must install the nbserverproxy
server extension This can be done
by running the command:
pip install nbserverproxy && jupyter serverextension enable --py nbserverproxy
Second, you must define a function to help create the URL that the browser
uses to connect to the Bokeh server. This will be passed into show()
in
the final step. A reference implementation is provided here, although you
must either modify it or define the environment variable EXTERNAL_URL
to the URL of your JupyterHub installation. By default, JupyterHub will set
JUPYTERHUB_SERVICE_PREFIX
.
def remote_jupyter_proxy_url(port):
"""
Callable to configure Bokeh's show method when a proxy must be
configured.
If port is None we're asking about the URL
for the origin header.
"""
base_url = os.environ['EXTERNAL_URL']
host = urllib.parse.urlparse(base_url).netloc
# If port is None we're asking for the URL origin
# so return the public hostname.
if port is None:
return host
service_url_path = os.environ['JUPYTERHUB_SERVICE_PREFIX']
proxy_url_path = 'proxy/%d' % port
user_url = urllib.parse.urljoin(base_url, service_url_path)
full_url = urllib.parse.urljoin(user_url, proxy_url_path)
return full_url
Finally, you can pass the function you defined in step 2 to show()
as the notebook_url keyword argument, which Bokeh will call while
setting up the server and creating the URL for loading the graph:
show(obj, notebook_url=remote_jupyter_proxy_url)
At this point, the Bokeh graph should load and execute python callbacks defined in your JupyterLab environment.
Trusting notebooks¶
Depending on the version of the Notebook in use, it may be necessary to “trust” the notebook in order for Bokeh plots to re-render when the notebook is closed and subsequently re-opened. The “Trust Notebook” option is typically located under the “File” menu:

Notebook Slides¶
It is possible to use the Jupyter notebook in conjunction with Reveal.js
to generate slideshows from notebook cell content. It is also possible to
include standalone (i.e. non-server) Bokeh plots in such sideshows, however
some steps must be followed for output to correctly display. Primarily: the
cell containing output_notebook
must be not be skipped.
The rendered cell output of the output_notebook
call is responsible
for making sure the BokehJS library is loaded. Without that, Bokeh plots
cannot function. If this cell type is marked “skip” then BokehJS will
not be loaded, and Bokeh plots will not display. An alternative, if you
wish to hide this cell, is to mark it as the “notes” slide type.
Notebook Handles¶
It is possible to update a previously shown plot in-place. When the argument
notebook_handle=True
is passed to show()
then a handle object is returned.
This handle object can be used with the push_notebook()
function to update
the plot with any recent changes to plots properties, data source values, etc.
This notebook handle functionality is only supported in classic Jupyter
notebooks and is not implemented in JupyterLab or Zeppelin yet.
The following screenshots walk through the basic usage of notebook handles.
First, import standard functions, as well as push_notebook()
:

Next, create some plots, and make sure to pass notebook_handle=True
to
show()
:

Looking at the handle, see that it is associated with the output cell for
In[2]
that was just displayed:

Now, update any properties of the plot, then call push_notebook()
with the
handle:

After doing so, note that the earlier output cell for In[2]
has changed
(without being re-executed)

More detailed demonstrations of using notebook handles can be found in the following example notebooks:
Jupyter Interactors¶
It is possible to drive updates to Bokeh plots using Jupyter notebook widgets,
known as interactors. The key doing this is the push_notebook()
function
described above. Typically it is called in the update callback for the
interactors, to update the plot from widget values. A screenshot of the
examples/howto/notebook_comms/Jupyter Interactors.ipynb example
notebook is shown below:

More Example Notebooks¶
Many more examples using Jupyter Notebook can be found in the bokeh-notebook repository. First clone the repository locally:
git clone https://github.com/bokeh/bokeh-notebooks.git
Then launch Jupyter Notebook in your web browser. Alternatively, live notebooks that can be run immediately online are hosted by Binder.
Additionally, there are some notebooks under examples in the main Bokeh repo:
Notebook comms examples:
IPyWidgets Outside the Notebook¶
In the previous section we learnt how to use Bokeh in JupyterLab and classical notebook environments. Suppose we would like to do the opposite and take advantage of the vibrant Jupyter ecosystem, in particular IPyWidgets, in a Bokeh application, outside the confines of those environments. This can be achieved with help from ipywidgets_bokeh extension to Bokeh:
$ conda install -c bokeh ipywidgets_bokeh
or
$ pip install ipywidgets_bokeh
Then you can use an IPyWidget in Bokeh, by simply wrapping it in IPyWidget
model and adding the wrapper to a document or including it in a layout. Given
that this is run outside Jupyter, there is no need for installing and/or
enabling any extensions.
Example¶
Suppose we would like to create an application with a single Jupyter slider and log its value to the console, as the slider is manipulated. We start by constructing the widget and configuring an observer, the same as we would do in Jupyter:
from ipywidgets import FloatSlider
angle = FloatSlider(min=0, max=360, value=0, step=1, description="Angle")
def on_change(change):
print(f"angle={change['new']} deg")
angle.observe(on_change, names="value")
To integrate the widget with Bokeh, we have to wrap it in IPyWidget
:
from ipywidgets_bokeh import IPyWidget
ipywidget = IPyWidget(widget=angle)
Then we add the wrapper to a Bokeh document:
from bokeh.plotting import curdoc
doc = curdoc()
doc.add_root(ipywidget)
To run this, assuming the code is saved under ipy_slider.py
, we issue
bokeh serve ipy_slider.py
(see Running a Bokeh Server for details). The
application is available at http://localhost:5006/ipy_slider.
From here, one can create more complex layouts and include advanced widgets, like ipyleaflet, ipyvolume, etc.