pythonsessionbokehdeploying

How to correctly deploy Bokeh app requiring server callbacks?


I want to use a Bokeh server to persist my plot and data, so I can embed my Bokeh app in a website. I'm trying to recreate the example given on the Bokeh 0.12.6 documentation:

from bokeh.client import push_session
from bokeh.embed import autoload_server
from bokeh.plotting import figure, curdoc

# figure() function auto-adds the figure to curdoc()
plot = figure()
plot.circle([1,2], [3,4])

session = push_session(curdoc())
script = autoload_server(plot, session_id=session.id)

So I'm starting a Bokeh server and running this python program as such:

bokeh serve --show animated.py

The error I'm getting looks like this:

File "session.py", line 298, in push:
raise IOError("Cannot push session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)") Traceback (most recent call last):
File "/Users/.../anaconda/lib/python3.5/site-packages/bokeh/application/handlers/code_runner.py", line 81, in run
exec(self._code, module.__dict__)
File "/Users/.../Documents/.../.../animated.py", line 9, in <module>
session = push_session(curdoc())
File "/Users/.../anaconda/lib/python3.5/site-packages/bokeh/client/session.py", line 86, in push_session
session.push(document)
File "/Users/.../anaconda/lib/python3.5/site-packages/bokeh/client/session.py", line 298, in push
raise IOError("Cannot push session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)")
OSError: Cannot push session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)

How should I go about fixing this problem? And if autoload_server() is the completely wrong approach, what are other ways to deploy a Bokeh app?


Solution

  • You'll want your bokeh app looking like:

    ### contents of app.py
    
    from bokeh.client import push_session
    from bokeh.embed import server_document
    from bokeh.plotting import figure, curdoc
    
    plot = figure()
    plot.circle([1,2], [3,4])
    
    doc = curdoc()
    doc.add_root(plot)
    

    You'll serve this via: (you may not need the origin kwarg, YMMV)

    bokeh serve app.py --allow-websocket-origin="*"
    

    Knowing that the server app is running at http://localhost:5006/ss (or whatever the terminal with the running app says), you create a script to load from there via

    script = autoload_server(url='http://localhost:5006/ss') # or whatever the location of the server process is.
    

    The you embed that script in your webpage somehow (perhaps loading the script into a jinja template), here it's copy pasted into a basic html template:

    <!doctype html>
    
    <html lang="en">
    <head> </head>
    
    <body>
      <script
          src="http://localhost:5006/ss/autoload.js?bokeh-autoload-element=435ac063-5288-41b9-8375-31907dd5f124&bokeh-app-path=/ss&bokeh-absolute-url=http://localhost:5006/ss"
          id="435ac063-5288-41b9-8375-31907dd5f124"
          data-bokeh-model-id=""
          data-bokeh-doc-id=""></script>
    </body>
    </html>
    

    Opening the above html doc should open a page with the plot.