Bokeh server is a wonderful tool and I am planning to use it in a project, but I first wanted to make sure it can be embedded in Flask. So far, I haven’t found any working example on the web.
The closest I came through is the following code:
The bokeh script:
#bokeh_plot.py
import pandas as pd
from bokeh.layouts import row, widgetbox
from bokeh.models import Select
from bokeh.palettes import Spectral5
from bokeh.plotting import curdoc, figure, show
from bokeh.sampledata.autompg import autompg
from bokeh.io import output_notebook
df = autompg.copy()
SIZES = list(range(6, 22, 3))
COLORS = Spectral5
ORIGINS = [‘North America’, ‘Europe’, ‘Asia’]
data cleanup
df.cyl = [str(x) for x in df.cyl]
df.origin = [ORIGINS[x-1] for x in df.origin]
df[‘year’] = [str(x) for x in df.yr]
del df[‘yr’]
df[‘mfr’] = [x.split()[0] for x in df.name]
df.loc[df.mfr==‘chevy’, ‘mfr’] = ‘chevrolet’
df.loc[df.mfr==‘chevroelt’, ‘mfr’] = ‘chevrolet’
df.loc[df.mfr==‘maxda’, ‘mfr’] = ‘mazda’
df.loc[df.mfr==‘mercedes-benz’, ‘mfr’] = ‘mercedes’
df.loc[df.mfr==‘toyouta’, ‘mfr’] = ‘toyota’
df.loc[df.mfr==‘vokswagen’, ‘mfr’] = ‘volkswagen’
df.loc[df.mfr==‘vw’, ‘mfr’] = ‘volkswagen’
del df[‘name’]
columns = sorted(df.columns)
discrete = [x for x in columns if df.dtype == object]
continuous = [x for x in columns if x not in discrete]
quantileable = [x for x in continuous if len(df.unique()) > 20]
def create_figure():
xs = df[x.value].values
ys = df[y.value].values
x_title = x.value.title()
y_title = y.value.title()
kw = dict()
if x.value in discrete:
kw['x_range'] = sorted(set(xs))
if y.value in discrete:
kw['y_range'] = sorted(set(ys))
kw['title'] = "%s vs %s" % (x_title, y_title)
p = figure(plot_height=600, plot_width=800, tools='pan,box_zoom,reset', **kw)
p.xaxis.axis_label = x_title
p.yaxis.axis_label = y_title
if x.value in discrete:
p.xaxis.major_label_orientation = pd.np.pi / 4
sz = 9
if size.value != 'None':
groups = pd.qcut(df[size.value].values, len(SIZES))
sz = [SIZES[xx] for xx in groups.codes]
c = "#31AADE"
if color.value != 'None':
groups = pd.qcut(df[color.value].values, len(COLORS))
c = [COLORS[xx] for xx in groups.codes]
p.circle(x=xs, y=ys, color=c, size=sz, line_color="white", alpha=0.6, hover_color='white', hover_alpha=0.5)
return p
def update(attr, old, new):
layout.children[1] = create_figure()
x = Select(title=‘X-Axis’, value=‘mpg’, options=columns)
x.on_change(‘value’, update)
y = Select(title=‘Y-Axis’, value=‘hp’, options=columns)
y.on_change(‘value’, update)
size = Select(title=‘Size’, value=‘None’, options=[‘None’] + quantileable)
size.on_change(‘value’, update)
color = Select(title=‘Color’, value=‘None’, options=[‘None’] + quantileable)
color.on_change(‘value’, update)
controls = widgetbox([x, y, color, size], width=200)
layout = row(controls, create_figure())
curdoc().add_root(layout)
curdoc().title = “Crossfilter”
The flask code:
#flask_app.py
from bokeh_plot import layout
from flask import render_template, Flask
from bokeh.embed import autoload_server
from bokeh.client import push_session
from bokeh.io import curdoc
from bokeh.resources import Resources
from bokeh.client import pull_session
app = Flask(name)
@app.route(‘/’)
def index():
session = pull_session(session_id=None, url='default')
curdoc().add_root(layout)
curdoc().title="Crossfilter"
push_session(curdoc())
tag = autoload_server(next(iter(session.document.roots)), session_id=session.id,
app_path='/unkn2', loglevel='debug')
session.close()
#tag = autoload_server(layout)
return render_template('app.html', tag=tag)
if name == ‘main’:
print("STARTED")
app.run(debug=True)
``
To execute this, I am first running bokeh serve and then python flask_app.py in another terminal, but that giving me this error when I visit localhost:5006:
-
File “D:\Dropbox\pi_pp\Bokeh examples\Flask\Unknown2\flask-app.py”, line 25, in
index
<img src="http://localhost:5000/?__debugger__=yes&cmd=resource&f=console.png" title="Open an interactive python shell in this frame" style="float: right; padding: 2px; margin-top: -3px; margin-right: 2px; display: block;">tag = autoload_server(next(iter(session.document.roots)), session_id=session.id,
StopIteration
Anyone have any idea how to fix this?