Bokeh app does not display in jupyter notebook using python 3.8.3 -- is this a bug?

Hello, I didn’t want to post this on the bugs page yet in case I am doing something incorrect.

The following code * works perfectly in a Jup notebook in a fresh python 3.7.3 venv, but the app does not display using identical code and python 3.8.3. Am I doing something wrong or should I open an issue?

This is just a regular venv with notebook and bokeh installed using pip (not conda or something else).

from bokeh.io import output_notebook, show
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, HoverTool
import pandas as pd 
import numpy as np
from bokeh.layouts import grid
from bokeh.models import Button, TextInput


output_notebook()

sample1 = np.random.multivariate_normal([0,0], [[1,0],[0,1]], 100)
sample2 = np.random.multivariate_normal([1,1], [[0.05,0],[0,0.05]], 100)
sample = np.concatenate([sample1, sample2])

df = pd.DataFrame(sample, columns=('x','y'))
df['value'] = np.sqrt(df['x']**2 + df['y']**2)
df.head()

source = ColumnDataSource(df)
tools = "box_zoom, undo, crosshair"

def modify_doc(doc):
    # same as before
    source = ColumnDataSource(df)
    p = figure(tools=tools)
    p.scatter('x','y', source=source, alpha=0.5)
    p.add_tools(
        HoverTool(
            tooltips=[('value','@value{2.2f}'), 
                      ('index', '@index')]
        )
    )
    
    # this function is called when the button is clicked
    def update():
        # number of points to be added, taken from input text box
        n = int(npoints.value)
        # new sample of points to be added. 
        # we use the a narrow gaussian centred on (-1, 1), 
        # and draw the requested number of points
        sample3 = np.random.multivariate_normal([-1,-1], [[0.05,0],[0,0.05]], n)
        df_new = pd.DataFrame(sample3, columns=('x','y'))
        df_new['value'] = np.sqrt(df['x']**2 + df['y']**2)
        # only the new data is streamed to the bokeh server, 
        # which is an efficient way to proceed
        source.stream(df_new)
    
    # GUI: 
    button = Button(label='add points:')
    npoints = TextInput(value="50")
    button.on_click(update)
    # arranging the GUI and the plot. 
    layout = grid([[button, npoints], p])
    doc.add_root(layout)

show(modify_doc)

* Codes comes from this tutorial: https://thedatafrog.com/en/articles/interactive-visualization-bokeh-jupyter/

Are there any messages in the browser’s JavaScript console log?

I did not check the console last night when I posted, but now the problem has gone from constant to intermittent.

I have also tried in 3.8.1, but cannot reproduce the problem. So far seems like it only happens 3.8.3 but so far I’ve only tried 3.8.1 and 3.7.3.

There are lots of messages in the console. I don’t know if will be helpful to just copy and paste the console log? Here it is:

menubar.js:263 actions jupyter-notebook:find-and-replace does not exist, still binding it in case it will be defined later...
MenuBar.bind_events @ menubar.js:263
bidi.js:19 Loaded moment locale en
extension.js:1 Failed to load resource: the server responded with a status of 404 (Not Found)
main.js:237 Widgets are not available.  Please install widgetsnbextension or ipywidgets 4.0
(anonymous) @ main.js:237
VM375 bokeh-2.0.2.min.js:238 [bokeh] setting log level to: 'info'
:44599/autoload.js?bokeh-autoload-element=1003&bokeh-absolute-url=http://localhost:44599&resources=none:1 Failed to load resource: net::ERR_CONNECTION_RESET
session.js:54 Session: kernel_created (1b7b38c0-73c5-437f-bf24-d6ebeb19009b)
kernel.js:462 Starting WebSockets: ws://localhost:8888/api/kernels/b8faffab-f213-464b-ad25-efbd08010e91
kernel.js:106 Kernel: kernel_connected (b8faffab-f213-464b-ad25-efbd08010e91)
kernel.js:106 Kernel: kernel_ready (b8faffab-f213-464b-ad25-efbd08010e91)
VM375 bokeh-2.0.2.min.js:238 [bokeh] setting log level to: 'info'
kernel.js:1008 Couldn't process kernel message TypeError: Cannot read property 'trim' of undefined
    at output (eval at append_javascript (outputarea.js:763), <anonymous>:47:39)
    at Kernel._handle_output_message (kernel.js:1197)
    at proxy (jquery.min.js:10502)
    at Kernel._handle_iopub_message (kernel.js:1224)
    at Kernel._finish_ws_message (kernel.js:1016)
    at kernel.js:1007
(anonymous) @ kernel.js:1008
Promise.catch (async)
Kernel._handle_ws_message @ kernel.js:1008
proxy @ jquery.min.js:10502
VM385:12 GET http://localhost:35717/autoload.js?bokeh-autoload-element=1003&bokeh-absolute-url=http://localhost:35717&resources=none net::ERR_CONNECTION_REFUSED
(anonymous) @ VM385:12
handleAddOutput @ VM370:86
dispatch @ jquery.min.js:5237
elemData.handle @ jquery.min.js:5044
trigger @ jquery.min.js:8471
(anonymous) @ jquery.min.js:8549
each @ jquery.min.js:367
each @ jquery.min.js:202
trigger @ jquery.min.js:8548
events.trigger @ events.js:31
OutputArea.append_output @ outputarea.js:355
OutputArea.handle_output @ outputarea.js:257
output @ codecell.js:395
Kernel._handle_output_message @ kernel.js:1197
proxy @ jquery.min.js:10502
Kernel._handle_iopub_message @ kernel.js:1224
Kernel._finish_ws_message @ kernel.js:1016
(anonymous) @ kernel.js:1007
Promise.then (async)
Kernel._handle_ws_message @ kernel.js:1007
proxy @ jquery.min.js:10502

@Ricyteach is your notebook running at a different url than the default localhost:8888? If so, you will have to supply the notebook_url parameter to show. I wish this was not the case, but the Jupyter team refuse to expose the front-end URL to the python kernel, as a matter of principle, so there is nothing we can do about that.

Also, FWIW definitely working for me with Python 3.8 and Bokeh 2.0.2:

No, that is not the problem; it is running on port 8888.

Thanks for checking. Is it 3.8.3?

Yes works on 3.8.3 for me as well. Is this running locally? If it’s remote there may be additional configuration needed to proxy the websocket.

Yes, locally running. Clean virtualenv.

Again to be clear: the problems seems to be intermittent now. I don’t know how to consistently reproduce it. But the failure to run definitely happens most of the time.

I’m wondering now if part of the problem is that I should install all of jupyter rather than just pip install notebook. But installing all of jupyter takes FOREVER.

Here’s another console log if it helps:

kernel.js:1008 Couldn't process kernel message TypeError: Cannot read property 'trim' of undefined
    at output (eval at append_javascript (outputarea.js:763), <anonymous>:47:39)
    at Kernel._handle_output_message (kernel.js:1197)
    at proxy (jquery.min.js:10502)
    at Kernel._handle_iopub_message (kernel.js:1224)
    at Kernel._finish_ws_message (kernel.js:1016)
    at kernel.js:1007
(anonymous) @ kernel.js:1008
Promise.catch (async)
Kernel._handle_ws_message @ kernel.js:1008
proxy @ jquery.min.js:10502
VM134:12 GET http://localhost:36711/autoload.js?bokeh-autoload-element=1091&bokeh-absolute-url=http://localhost:36711&resources=none net::ERR_CONNECTION_REFUSED
(anonymous) @ VM134:12
handleAddOutput @ VM109:86
dispatch @ jquery.min.js:5237
elemData.handle @ jquery.min.js:5044
trigger @ jquery.min.js:8471
(anonymous) @ jquery.min.js:8549
each @ jquery.min.js:367
each @ jquery.min.js:202
trigger @ jquery.min.js:8548
events.trigger @ events.js:31
OutputArea.append_output @ outputarea.js:355
OutputArea.handle_output @ outputarea.js:257
output @ codecell.js:395
Kernel._handle_output_message @ kernel.js:1197
proxy @ jquery.min.js:10502
Kernel._handle_iopub_message @ kernel.js:1224
Kernel._finish_ws_message @ kernel.js:1016
(anonymous) @ kernel.js:1007
Promise.then (async)
Kernel._handle_ws_message @ kernel.js:1007
proxy @ jquery.min.js:10502
VM115 bokeh-2.0.2.min.js:238 [bokeh] setting log level to: 'info'

And here is a log from a time when it was successful:

kernel.js:1008 Couldn't process kernel message TypeError: Cannot read property 'trim' of undefined
    at output (eval at append_javascript (outputarea.js:763), <anonymous>:47:39)
    at Kernel._handle_output_message (kernel.js:1197)
    at proxy (jquery.min.js:10502)
    at Kernel._handle_iopub_message (kernel.js:1224)
    at Kernel._finish_ws_message (kernel.js:1016)
    at kernel.js:1007
(anonymous) @ kernel.js:1008
Promise.catch (async)
Kernel._handle_ws_message @ kernel.js:1008
proxy @ jquery.min.js:10502
VM115 bokeh-2.0.2.min.js:238 [bokeh] setting log level to: 'info'
VM115 bokeh-2.0.2.min.js:551 [bokeh] Websocket connection 1 is now open
VM115 bokeh-2.0.2.min.js:162 [bokeh] document idle at 141 ms
VM115 bokeh-2.0.2.min.js:160 Bokeh items were rendered successfully

Are the problems with only your notebook? What happens with the example in the repo:

https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/notebook_embed.ipynb

Good question, and apologies for the unnecessarily complicated example.

No, it happens with any notebook when attempting to use the pattern:

def myapp(doc): ...

show(myapp)

It does NOT happen when you do something like:

p = figure()
show(p)

Can you check with different browsers and/or platforms?

Yes I’ll get back to you tomorrow on that-- I’m on Linux here at home (actually a Chromebook with the Linux Beta but it’s really just Debian), but I use Windows at the office.

Had a busy week; finally confirmed this problem does not occur- never happens- using the Python installation on my Windows machine at work, nor does it occur on the Debian WSL on the same machine.

However, it is back to occurring 100% of the time on my Chromebook, and I have now replicated it in Linux on two different Chromebooks, both of them Acers running ChromeOS v. 83 (but different models), and it occurs using both Python 3.7.3 and 3.8.3.

I have not been able to find any concrete information. There are various allusions to ChromeOS being configured in some way by default to to like connections to localhost, e.g.

You might try loading the autoload URL from the console log directly in a URL bar, seeing if there are any relevant settings (e.g. maybe something mentioned in that SO post above), or (if possible?) try other browsers on the Chromebook. Unfortunately I do not have access to any Chromebook to experiment.

hmmm I’m far less knowledgeable than you I am certain but I’m unsure if that is helpful since the browser is able to read localhost:8888 just fine, based on the fact that is where the notebook is being served from. And as shown in the example code, the output_notebook() function is being run so the bokeh app should appear inside the notebook.

I will look into trying an alternative browser.

I could also try setting up a remote notebook server and seeing if the problem persists for a remote client. But I am not sure how to set that up.

I’m just grasping as straws, really. The relevant, important line in the console log is this:

VM134:12 GET http://localhost:36711/autoload.js?bokeh-autoload-element=1091&bokeh-absolute-url=http://localhost:36711&resources=none net::ERR_CONNECTION_REFUSED

When you show a Bokeh app in a notebook, Bokeh installs URL handlers for routes like the one above on the notebook’s Tornado IOLoop. Then the Jupyter Kernel makes an HTTP request to those URLs to connect and display the app in an output cell. Something on your system is blocking that HTTP request from succeeding, but I am afraid I don’t have any clear idea what.

Trying to install Konqueror now but it’s going to be a while. Will report back.

Konquerer install finished faster than I thought it would-- and everything works perfectly in there! Very very odd. So I guess this means it is something going on in the Chrome 83.

My Chrome just pinged me to install an update; I’m going to try installing it and seeing what happens. EDIT: nope, no help there. EDIT: worth noting the same versions of the Chrome browser (down to the smallest subversion number) are now reported to be installed on the Windows machine and the Chromebooks.