Python Bokeh交互式疏散模拟图浏览器加载失败(超时+Token过期)
Bokeh模拟图加载超时与令牌过期问题修复方案
核心问题定位
ProtocolError("Token is expired.")和浏览器长时间加载超时,本质是Bokeh会话令牌有效期不足,或模拟逻辑阻塞服务IO循环导致的服务无响应。
具体修复步骤
1. 延长会话超时时间
启动Bokeh服务时显式设置更长的会话有效期,比如2小时(7200秒):
from bokeh.server.server import Server def create_doc(doc): # 你的绘图与模拟逻辑 pass # 启动服务时指定超时参数 server = Server({'/': create_doc}, session_timeout=7200) server.start() server.io_loop.add_callback(server.show, "/") server.io_loop.start()
如果用命令行启动服务,添加参数:
bokeh serve --show your_script.py --session-timeout 7200
2. 隔离模拟逻辑到后台线程
长时间运行的疏散模拟会阻塞Bokeh的IO循环,导致服务无法响应浏览器请求,必须把模拟逻辑放到后台线程:
from threading import Thread from bokeh.models import ColumnDataSource import time def simulation_loop(source): # 你的灾难疏散模拟逻辑 while True: # 更新疏散主体的位置数据 new_positions = {'x': [...], 'y': [...]} # 替换为实际模拟数据 source.stream(new_positions, rollover=100) time.sleep(0.1) # 控制模拟帧率,避免资源占用过高 def create_doc(doc): source = ColumnDataSource(data={'x': [], 'y': []}) # 创建交互式绘图(比如散点图表示疏散人员) plot = figure(...) plot.circle(x='x', y='y', source=source) doc.add_root(plot) # 启动后台模拟线程,设置为守护线程避免程序无法正常退出 sim_thread = Thread(target=simulation_loop, args=(source,), daemon=True) sim_thread.start()
3. 排除端口占用问题
默认端口5006被占用会导致服务异常,可指定空闲端口启动:
server = Server({'/': create_doc}, port=5007, session_timeout=7200)
或命令行:
bokeh serve --show your_script.py --port 5007
4. 极简代码验证服务可用性
先运行极简示例,确认Bokeh服务本身正常,再接入你的模拟逻辑:
from bokeh.plotting import figure, curdoc from bokeh.models import ColumnDataSource from threading import Thread import time source = ColumnDataSource(data={'x': [0], 'y': [0]}) p = figure(title="测试Bokeh服务") p.circle(x='x', y='y', source=source, size=10) def update_data(): i = 0 while True: source.stream({'x': [i], 'y': [i]}) i += 1 time.sleep(0.5) Thread(target=update_data, daemon=True).start() curdoc().add_root(p)
用bokeh serve --show test_script.py启动,若浏览器能正常显示动态点,则服务本身无问题,再排查你的模拟逻辑。
额外注意事项
- 避免在Jupyter Notebook中长时间运行Bokeh服务,建议使用独立Python脚本启动。
- 模拟循环中不要使用无限制的
while True,可添加终止条件避免资源浪费。
内容的提问来源于stack exchange,提问作者Vondoe79
相关产品推荐
相关产品推荐

