What's the correct way to use widgets with bokeh inside jupyter notebooks

I’m trying to update a plot using widgets with bokeh. My understanding is that bokeh’s widgets either work only with javascript updates or using the bokeh server. For those reasons I tried using ipywidgets and they somewhat work but a new plot is generated every time instead of updating the original plot. How do I achieve that?

Here’s how I tried doing it:

import bokeh.plotting as bkpl
import bokeh.io as bki
import ipywidgets as widgets
from IPython.display import display as idisplay


bki.output_notebook()

x = [1, 2, 3, 4, 5]
y = [6, 7, 2, 4, 5]

p = bkpl.figure(title="My chart", x_axis_label='x', y_axis_label='y')
p.line(x, y, legend_label="Some line", line_width=2)

def callback(evt):
    bkpl.show(p)

w = widgets.Button(description='Replot')

w.on_click(callback)
display(w)

bkpl.show(p)

You’re probably looking for a pure Bokeh solution, but if you are comfortable adding a dependency on Panel, you can wrap your Bokeh figure into a Panel container like pn.Row, and then the widgets should work smoothly in or out of Jupyter. See the Panel Bokeh pane docs for details.

I figured how to do it. I had to get a handle from the show function and pass it to the push_notebook function:

import bokeh.plotting as bkpl
import bokeh.io as bki
import ipywidgets as widgets
from IPython.display import display as idisplay
import random


bki.output_notebook()

x = [1, 2, 3, 4, 5]
y = [6, 7, 2, 4, 5]

p = bkpl.figure(title="My chart", x_axis_label='x', y_axis_label='y')
p.line(x, y, legend_label="Some line", line_width=2)

def callback(evt):
    p.line(x, [random.randint(0,10) for _ in range(5)], legend_label="Other Line", line_width=2)
    bki.push_notebook(handle=handle)
    #bkpl.show(p)

w = widgets.Button(description='Replot')

w.on_click(callback)
display(w)

handle = bkpl.show(p, notebook_handle=True)

Other suggestions are very welcome.

Huh. I do see why that would work, although to be honest it’s not what was in mind for push_notebook. All of our old examples for push_notebook are used in callbacks for ipywidgets rather than Bokeh’s widgets, since that was the original motivating use-case for push_notebook (a very long time ago now).

Just being clear, push_notebook is quite limited relative to embedded a Bokeh app in the notebook. Bokeh apps can support full two-way events between the “Python side” and the “JavaScript side”. As the name suggests, push_notebook is only capable to push updates in one direction, from Python to BokehJS.