Running bokeh server programmatically to show in browser locally

Viewed 3766

I am making an interactive data manipulation with bokeh (0.12.6) utility that I will deploy within a package. The idea is that a user can run a some routine module.utility() that will start the bokeh server, launch the application in a browser, and when the tab or browser are closed, the server will be stopped.

My application launches fine if I run bokeh serve --show myapp, but it hangs when connecting to the localhost using my method described below. I've inspected the handlers, everything looks as it should.

Is this a reasonable thing to do, and am I going about it correctly?

Directory format

<installed module path>/myapp
└── main.py

Where ./myapp will reside in venv/lib/python3.5/site-packages/mymodule etc.

main.py

from bokeh.io import curdoc
from bokeh.layouts import column
from bokeh.plotting import figure
from bokeh.models.sources import ColumnDataSource

source = ColumnDataSource(dict(x=list(range(5)), y=list(range(5))))

p = figure(width=300, height=300, tools=[], toolbar_location=None)
p.line(x='x', y='y', source=source)

curdoc().add_root(column(p, sizing_mode='scale_width'))

Run script

def run_single_server(abs_app_path, port=5000):
    '''Run bokeh application for single session from server`'''
    from bokeh.application import Application
    from bokeh.application.handlers import DirectoryHandler
    from bokeh.server.server import Server
    import os

    app_name = os.path.split(abs_app_path)[1]
    url = '/{}'.format(app_name)

    # Start a bokeh server
    apps = {url:Application(DirectoryHandler(filename=abs_app_path))}
    server = Server(apps, port=port)
    server.start()
    server.show(url)

    # somehow wait for session to end, perhaps using `server_lifecycle.py`

    server.stop()

    return

def utility():
    import mymodule

    module_path = os.path.split(mymodule.__file__)[0]
    abs_app_path = os.path.join(module_path, 'myapp')

    run_single_server(abs_app_path, port=5000)

    return

Perhaps have that routine in the main __init__.py, and have it work like this:

import mymodule
mymodule.utility()

# 1. Browser launches
# 2. user does stuff
# 3. user closes window
# 4. bokeh server is shutdown

Update I found the build_single_handler_application routine and tried that, but it also appears to hang.

from bokeh.command.util import build_single_handler_application
import os

app_name = os.path.split(abs_app_path)[1]
url = '/{}'.format(app_name)

# Start a bokeh server
apps = build_single_handler_application(abs_app_path)
1 Answers
Related