Skip to content

Instantly share code, notes, and snippets.

@Wildcarde
Last active February 7, 2023 21:15
Show Gist options
  • Save Wildcarde/6841f00f0a0cd52ade09964a0fdb5684 to your computer and use it in GitHub Desktop.
Save Wildcarde/6841f00f0a0cd52ade09964a0fdb5684 to your computer and use it in GitHub Desktop.
Quick demo embedding a Bokeh chart inside a Flask application

This works in a python 3.6 environment with bokeh and flask installed. To use this you need the following directory structure:

app/
 - templates/
   - hello.html
 - bokeh-slider.py
 - hello.py

After that you need to open two terminals at app/, in the first one you need to run the bokeh server with the command:

bokeh serve ./bokeh-sliders.py --allow-websocket-origin=127.0.0.1:5000

In the second one run the command:

python hello.py

After this the webpage should 'just work' by opening a webpage to http://localhost:5000

''' Present an interactive function explorer with slider widgets.
Scrub the sliders to change the properties of the ``sin`` curve, or
type into the title text box to update the title of the plot.
Use the ``bokeh serve`` command to run the example by executing:
bokeh serve sliders.py
at your command prompt. Then navigate to the URL
http://localhost:5006/sliders
in your browser.
'''
import numpy as np
from bokeh.io import curdoc
from bokeh.layouts import row, widgetbox
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import Slider, TextInput
from bokeh.plotting import figure
# Set up data
N = 200
x = np.linspace(0, 4*np.pi, N)
y = np.sin(x)
source = ColumnDataSource(data=dict(x=x, y=y))
# Set up plot
plot = figure(plot_height=400, plot_width=400, title="my sine wave",
tools="crosshair,pan,reset,save,wheel_zoom",
x_range=[0, 4*np.pi], y_range=[-2.5, 2.5])
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)
# Set up widgets
text = TextInput(title="title", value='my sine wave')
offset = Slider(title="offset", value=0.0, start=-5.0, end=5.0, step=0.1)
amplitude = Slider(title="amplitude", value=1.0, start=-5.0, end=5.0)
phase = Slider(title="phase", value=0.0, start=0.0, end=2*np.pi)
freq = Slider(title="frequency", value=1.0, start=0.1, end=5.1)
# Set up callbacks
def update_title(attrname, old, new):
plot.title.text = text.value
text.on_change('value', update_title)
def update_data(attrname, old, new):
# Get the current slider values
a = amplitude.value
b = offset.value
w = phase.value
k = freq.value
# Generate the new curve
x = np.linspace(0, 4*np.pi, N)
y = a*np.sin(k*x + w) + b
source.data = dict(x=x, y=y)
for w in [offset, amplitude, phase, freq]:
w.on_change('value', update_data)
# Set up layouts and add to document
inputs = widgetbox(text, offset, amplitude, phase, freq)
curdoc().add_root(row(inputs, plot, width=800))
curdoc().title = "Sliders"
<html>
<head>
<title>Website</title>
<style>
@import url(http://fonts.googleapis.com/css?family=Amatic+SC:700);
body{
text-align: center;
}
h1{
font-family: 'Amatic SC', cursive;
font-weight: normal;
color: #8ac640;
font-size: 2.5em;
}
</style>
</head>
<body>
<p>Flask embedding Bokeh test</p>
{{ bokS|indent(4)|safe }}
</body>
</html>
from flask import Flask, flash, redirect, render_template, request, session, abort
from bokeh.embed import autoload_server
app = Flask(__name__)
@app.route("/")
def hello():
script=autoload_server(model=None,app_path="/bokeh-sliders",url="http://localhost:5006")
return render_template('hello.html',bokS=script)
if __name__ == "__main__":
app.run()
@sameerCoder
Copy link

Hi,
Can you help me in this bokeh dynamic plot , where i am missing the stuff ,
I am getting bokeh plot in flask embedded in webpage but it is static not dynamic .,
Do i have to write function for current document / modify doc . link is below there u can find details.
https://stackoverflow.com/questions/62077389/bokeh-embedded-plot-not-acting-dynamic-in-flask-app-with-no-error
Thankyou.

@Wildcarde
Copy link
Author

@sameerCoder i don't actually work with this code like... ever. When I was working on this I was just stitching something together for my wife's data science class so they had a building block to work from and honestly had no idea people were commenting on this I only recently changed my email notifications and started getting comments on my gists.

however a quick glance at your SO post makes me suspect bokeh isn't being run as an active server like i have here. The aboves structure is:
bokeh app running free standing
flask app running free standing, it generates a unique id number for the script on each connection to the route / so that individual users have independent instances of the bokeh app.

This setup requires running 2 entirely separate processes, rather than embedding all of the code into a single script.

These days i'd probably make this more complicated and use something like supervisord to launch the independent scripts (or put them in their own docker containers and use compose).

@Wildcarde
Copy link
Author

To anybody else that has asked a question on this in the past, sorry I didn't follow up with you. I legit had no idea people were commenting on this post. I'm guessing several years later you no longer need help puzzling this out; and i suspect that things have changed significantly in the mean time. Sorry!

@sameerCoder
Copy link

@Wildcarde
Hi,
Thanks for reply.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment