在网站中使用Python/bokeh嵌入图表
我正在尝试把一个bokeh图表静态嵌入到我的个人网站上,但遇到了一些我不太明白的情况。基本上,我是这样生成图表的:
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/')
到目前为止,一切正常。这会生成一个文件,名字像是(random garbage).embed.js
,还有一段包含html语法的字符串,我手动把它复制到一个叫testembed.html
的html文件中,下面是我复制的内容:
<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>
如果我让python代码引用我本地的python安装,并把生成的文件(.html和.embed.js)复制到我的本地电脑上,我可以看到html文件中的图表。
但是,我真正想做的是让这个在远程电脑上运行,并通过我的个人网站在网上访问这个html文件。
当我让static_path
指向我远程电脑的python安装(如上所示,已注释掉),我在网上访问html页面时(也就是去http://mywebsite.com/testembed.html),却看不到图表。我不知道为什么会这样。
作为参考,这里是定义html片段函数的代码:
https://github.com/ContinuumIO/bokeh/blob/master/bokeh/objects.py#L309
我注意到有一个选项我没有在create_html_snippet
中传递,即embed_base_url
,这可能和这个问题有关。
提前谢谢你们! Mike
编辑
我采纳了bigreddot
的建议,解决了这个问题。实际上,我遇到的问题是我使用的网络服务器出于安全原因,只能访问我public_html
目录中的内容。解决方法是用rsync
把bokeh/static
目录同步到我的public_html
中,并指向那个目录:
rsync -ax /opt/anaconda/lib/python2.7/site-packages/bokeh/server/static/ /home/myusername/public_html/bokeh-static/
然后我把我的代码修改如下:
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')
然后显然要把生成的html复制到testembed.html
中。
2 个回答
编辑:这个回答中的信息是关于非常旧版本的Bokeh,现在已经不再适用。
embed_base_url
控制着JavaScript查找嵌入文件的URL路径(可以是绝对路径或相对路径)。
embed_save_loc
控制Python将嵌入文件写入的目录。当设置为server=True时,embed_save_loc就不需要了。
static_path
控制JavaScript用来构建bokeh.js和bokeh.css的URL路径(同样可以是绝对路径或相对路径)。默认情况下,它指向 http://localhost:5006/static/
,但也可以指向一个CDN。
运行bokeh服务器时,访问 http://localhost:5006/bokeh/generate_embed/static
。我觉得这需要你在主分支上运行,因为有个bug。
编辑:CDN是“内容分发网络”的缩写,只是一个文件服务器的 fancy 说法。例如,我们在 http://cdn.bokeh.org/bokeh-0.4.2.js(或者 http://cdn.bokeh.org/bokeh-0.4.2.min.js)上托管bokeh.js,供任何人使用。
更新:原问题中提到的 create_html_snippet
函数已经被弃用并在多年前移除了。现在有多种更新的方法可以在 bokeh.embed
模块中嵌入 Bokeh 内容。下面将总结一些这些方法。
独立内容
独立的 Bokeh 内容是纯 HTML/JS/CSS,不依赖于运行中的 Bokeh 服务器。不过,独立的 Bokeh 内容仍然可以非常互动,包含绘图工具(例如平移、缩放、选择)、链接刷选和触发 CustomJS 动作的小部件。有几种方法可以嵌入独立内容:
json_item
如果你想创建一个纯 JSON 格式的内容,可以被 JS 函数加载,你可以使用 json_item
函数。例如,你可以通过 Flask 的一个接口来提供 JSON:
@app.route('/plot')
def plot():
p = make_plot('petal_width', 'petal_length')
return json.dumps(json_item(p, "myplot"))
然后页面可以用类似这样的 JavaScript 代码加载和渲染内容:
<div id="myplot"></div>
<script>
fetch('/plot')
.then(function(response) { return response.json(); })
.then(function(item) { Bokeh.embed.embed_item(item); })
</script>
这假设你已经在页面上加载了 BokehJS 库,比如在页面的 <head>
部分使用 CDN.render()
。可以查看 这里的完整最小示例。
components
如果你想生成一个简单的 <script>
标签和 <div>
,可以嵌入到页面中,你可以使用 components
函数:
from bokeh.plotting import figure
from bokeh.embed import components
plot = figure()
plot.circle([1,2], [3,4])
script, div = components(plot)
返回的 script
和 div
(如果你传入多个项目则返回多个 div)可以插入到页面中:
<!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>
和上面一样,你需要在页面头部硬编码或模板化 BokehJS 的 JS 和 CSS 资源,例如使用 CDN.render()
。
file_html
如果你想生成完整的 HTML 页面(即包括 <head></head><body></body>
),你可以使用 file_html
函数:
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")
这会生成一个基本页面,可以保存或提供等。如果需要,你也可以提供自己的 Jinja 模板(具体细节见文档)。
Bokeh 服务器应用
Bokeh 服务器应用可以将 Bokeh 图表和小部件连接到一个实时运行的 Python 进程,这样像用户界面交互、选择或小部件操作等事件就可以触发真实的 Python 代码(例如 Pandas 或 scikit-learn)。
要在页面模板中嵌入一个基本的 Bokeh 应用,最常用的方法是使用 server_document
:
from bokeh.embed import server_document
script = server_document("https://demo.bokeh.org/slider")
返回的 script
可以在 HTML 页面中的任何地方进行模板化,Bokeh 应用将出现在那里。还有许多其他可能性,例如单独嵌入应用组件、为用户定制会话,或在代理/负载均衡器后运行。Bokeh 服务器可能还需要配置以允许访问嵌入页面。有关详细信息,请参见用户指南的 运行 Bokeh 服务器 章节。
另一种可能更简单的“嵌入” Bokeh 服务器应用的方法,是使用指向正在运行的 Bokeh 应用公共 URL 的 IFrame。