I am trying to statically embed a bokeh plot in a personal website, and am encountering some behavior I do not understand. Basically, I am generating a plot using bokeh as follows:
import bokeh.plotting as bplt
import numpy as np
x=np.random.random(100)
y=np.random.random(100)
bplt.output_file("t.html")
plot=bplt.line(x,y)
##the following line refers to the bokeh installed on my home computer
print plot.create_html_snippet(
static_path='/usr/local/lib/python2.7/site-packages/bokeh/server/static/')
##the following line refers to the bokeh installed on my remote computer
#print plot.create_html_snippet(
# static_path='/opt/anaconda/lib/python2.7/site-packages/bokeh/server/static/')
So far so good. This produces a file that looks like (random garbage).embed.js
, and a prints string containing html syntax that I manually copy into an html file I am calling testembed.html
, which I have reproduced below:
<html>
<body>
<h2>Simple Embed Example</h2>
<p>This is where my plot should be:</p>
<p>
<!--The next 4 lines are the output of the print statement from the python code-->
<script src="ccbd451a-6995-4dd2-b99c-e4140b362997.embed.js"
bokeh_plottype="embeddata"
bokeh_modelid="ccbd451a-6995-4dd2-b99c-e4140b362997"
bokeh_modeltype="Plot" async="true"></script>
</p>
</body>
</html>
If I have the python code reference my local python installation and copy the generated files (.html and .embed.js) to my local computer, I can see the plot in the html file.
However, what I really want to do is have this run on a remote computer, and have the html file accessible through the web on my personal site.
When I have static_path
refer to my remote computer's python install (as shown above, commented out), I can't see the plot in the html page when I access it through the web (ie, going to http://mywebsite.com/testembed.html). I have no idea why this is happening.
For reference, here is the code where the html snippet function is defined:
https://github.com/ContinuumIO/bokeh/blob/master/bokeh/objects.py#L309
and I note there is an option I am not passing in create_html_snippet
, ie, embed_base_url
, which could have something to do with this.
Thanks in advance! Mike
EDIT
I took bigreddot
's advice, which solved the problem. The actual problem I had been having was that the webserver I was using was, for security purposes, only able to access things in my public_html
directory. The workaround was to rsync
the bokeh/static
directory into my public_html
and point to that:
rsync -ax /opt/anaconda/lib/python2.7/site-packages/bokeh/server/static/ /home/myusername/public_html/bokeh-static/
and then modify my code as follows:
import bokeh.plotting as bplt
import numpy as np
x=np.random.random(100)
y=np.random.random(100)
bplt.output_file("t.html")
plot=bplt.line(x,y)
#the following line refers to the bokeh rsynced to my directory
print plot.create_html_snippet(
static_path='http://www.my_server_website/~myusername/bokeh-static/',
embed_base_url = 'http://www.my_server_website/~myusername/where_.js_file_is_located')
and then obviously copy the generated html into the testembed.html
.
UPDATE: the create_html_snippet
function mentioned in the original question was deprecated and removed years ago. There are now various newer ways to embed Bokeh content available in the bokeh.embed
module. This answer will summarize some of them.
Standalone Bokeh content is pure HTML/JS/CSS that is not backed by a running Bokeh server. However, standalone Bokeh content can still be highly interactive, with plot tools (e.g. pan, zoom, selection), linked brushing, and widgets that trigger CustomJS actions. There are several ways to embed standalone content:
json_item
If you would like to create a pure JSON representation of the content that can be loaded by JS functions, you can use the json_item
function. As an example, you might server the JSON from a Flask endpoint:
@app.route('/plot')
def plot():
p = make_plot('petal_width', 'petal_length')
return json.dumps(json_item(p, "myplot"))
Then the page can load and render the content with JavaScript code like this:
<div id="myplot"></div>
<script>
fetch('/plot')
.then(function(response) { return response.json(); })
.then(function(item) { Bokeh.embed.embed_item(item); })
</script>
This assumes you have loaded the BokehJS library on the page, e.g. by templating CDN.render()
in the <head>
of the page. See a complete minimal example here.
components
If you would like to generate a simple <script>
tag and <div>
that can be templated into a page to, you can use the components
function:
from bokeh.plotting import figure
from bokeh.embed import components
plot = figure()
plot.circle([1,2], [3,4])
script, div = components(plot)
The returned script
and div
(or divs it you pass multiple items) can be inserted in to page:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bokeh Scatter Plots</title>
<!-- COPY/PASTE BOKEHJS RESOURCES HERE -->
<!-- COPY/PASTE SCRIPT HERE -->
</head>
<body>
<!-- INSERT DIVS HERE -->
</body>
</html>
As above, you will need to hardcode or template the BokehJS JS and CSS resources in the page head, e.g. with CDN.render()
file_html
If you want to generate entire complete HTML pages (i.e. including <head></head><body></body>
), you can use the file_html
function:
from bokeh.plotting import figure
from bokeh.resources import CDN
from bokeh.embed import file_html
plot = figure()
plot.circle([1,2], [3,4])
html = file_html(plot, CDN, "my plot")
This generates a basic page that can be saved or served, etc. If desired you can also supply your own Jinja template (see docs for details).
Bokeh server applications can connect Bokeh plots and widgets to a live running Python process, so that events like UI interactions, making selections, or widget manipulations can trigger real Python code (e.g. Pandas or scikit-learn).
To embed a basic Bokeh application in a page template, the most common method is to use server_document
:
from bokeh.embed import server_document
script = server_document("https://demo.bokeh.org/slider")
The returned script
can be templated anywhere in an HTML page, and the Bokeh application will appear there. There are many other possibilities, e.g. embedding app components individually, customizing sessions for users, or running behind proxies/load balancers. The Bokeh server may also need to be configured to allow access to the embedding page. For full details see the Running a Bokeh Server chapter of the Users Guide.
Another, possibly simpler way to "embed" a Bokeh server application, is to use IFrames pointing at the public URL of a running Bokeh app.