You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bokeh 3.3.0服务器:如何通过Tornado API托管图片文件夹实现悬停提示图

Bokeh服务中HoverTool提示框图片无法加载的解决方案

问题背景

在远程服务器上使用Bokeh 3.3.0和Tornado运行可视化服务,图表渲染正常,但鼠标悬停标记时提示框内的图片无法访问。核心原因是图片文件夹未被Tornado托管,导致无法通过HTTP路径访问图片。

现有代码

from bokeh.layouts import column
from bokeh.models import ColumnDataSource,HoverTool
from bokeh.plotting import figure
from bokeh.server.server import Server

def bkapp(doc):
    
    #get necessary data...
    dfsource=ColumnDataSource(df)

    hover = HoverTool(tooltips ="""
        <div>
            <div>
                <img
                    src="@_id.png"
                    style="float: left; margin: 0px 5px 5px 0px;"
                    border="2"
                ></img>
            </div>
            <div>
                <span style="font-size: 15px;">@_id</span>
                <span style="font-size: 10px; color: #696;">(@ucx, @ucy)</span>
            </div>
        """)

    # create a plot
    p = figure(sizing_mode="stretch_width", max_width=2000, height=800,
              tools=["pan", 'wheel_zoom',"tap","reset"])
    p.add_tools(hover)

    circle = p.circle(source=dfsource,x="ucx",y="ucy")

    doc.add_root(p)

server = Server({'/': bkapp}, num_procs=4)
server.start()

if __name__ == '__main__':
    print('Opening Bokeh application on http://localhost:5006/')

    server.io_loop.add_callback(server.show, "/")
    server.io_loop.start()

文件夹结构

-cwd
--myapp.py
--imagefolder/

已尝试的图片路径

  • src="imagefolder/@_id.png"
  • src="file://@_id.png"
  • src="http://localhost:5006/@_id.png"

解决方案:让Tornado托管图片文件夹

要让Bokeh的Tornado服务器托管静态资源文件夹,需通过Server类的extra_patterns参数添加静态路由,具体步骤如下:

  1. 导入Tornado静态文件处理器:引入tornado.web.StaticFileHandler处理静态文件请求。
  2. 配置静态路由:创建Server实例时,通过extra_patterns添加指向imagefolder的路由,映射本地文件夹路径与HTTP访问前缀。
  3. 修正HoverTool图片路径:将src改为托管后的HTTP路径"/imagefolder/@_id.png"。

修改后的完整代码

from bokeh.layouts import column
from bokeh.models import ColumnDataSource, HoverTool
from bokeh.plotting import figure
from bokeh.server.server import Server
from tornado.web import StaticFileHandler
import os

def bkapp(doc):
    
    # get necessary data...
    dfsource = ColumnDataSource(df)

    hover = HoverTool(tooltips ="""
        <div>
            <div>
                <img
                    src="/imagefolder/@_id.png"
                    style="float: left; margin: 0px 5px 5px 0px;"
                    border="2"
                    width="100"
                ></img>
            </div>
            <div>
                <span style="font-size: 15px;">@_id</span>
                <span style="font-size: 10px; color: #696;">(@ucx, @ucy)</span>
            </div>
        """)

    # create a plot
    p = figure(sizing_mode="stretch_width", max_width=2000, height=800,
              tools=["pan", 'wheel_zoom',"tap","reset"])
    p.add_tools(hover)

    circle = p.circle(source=dfsource, x="ucx", y="ucy")

    doc.add_root(p)

# 获取当前脚本所在目录的绝对路径
current_dir = os.path.dirname(os.path.abspath(__file__))
# 配置静态路由:将/imagefolder/路径映射到本地imagefolder文件夹
extra_patterns = [
    (r"/imagefolder/(.*)", StaticFileHandler, {"path": os.path.join(current_dir, "imagefolder")})
]

# 创建Server实例时传入extra_patterns
server = Server({'/': bkapp}, num_procs=4, extra_patterns=extra_patterns)
server.start()

if __name__ == '__main__':
    print('Opening Bokeh application on http://localhost:5006/')
    print('Images accessible at http://localhost:5006/imagefolder/[image_name].png')

    server.io_loop.add_callback(server.show, "/")
    server.io_loop.start()

关键说明

  • 静态路由配置:(r"/imagefolder/(.*)", StaticFileHandler, {"path": ...}) 表示所有以/imagefolder/开头的请求,都会转发到本地imagefolder文件夹匹配对应图片。
  • 绝对路径使用:通过os.path模块获取绝对路径,避免因运行目录变化导致的路径错误,适配远程服务器环境。
  • 路径一致性:HoverTool中的图片路径必须与静态路由完全匹配,确保前端能正确请求到图片资源。

内容的提问来源于stack exchange,提问作者lesolorzanov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 22:30:38