在网站中使用Python/bokeh嵌入图表

16 投票
2 回答
22950 浏览
提问于 2025-04-17 21:54

我正在尝试把一个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目录中的内容。解决方法是用rsyncbokeh/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 个回答

3

编辑:这个回答中的信息是关于非常旧版本的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,供任何人使用。

20

更新:原问题中提到的 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)

返回的 scriptdiv(如果你传入多个项目则返回多个 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。

撰写回答