Bokeh CustomJS解构实例错误:Jupyter正常运行但Streamlit环境失效求助
报错原因分析
这个报错本质是Bokeh尝试遍历非数组类型的数据源字段,核心诱因有2个:
- 变量
x未做兜底校验:你在if分支内用var声明x,如果选择框的值没有匹配到任何src里的记录,x会是undefined,此时取src.data['mean'][undefined]返回的是undefined,赋值给src2的字段后,Bokeh内部需要迭代该字段渲染时就会触发非可迭代实例的报错。Jupyter环境可能默认做了空值兼容,而Streamlit的Bokeh组件序列化逻辑更严格,所以会报错。 - 嵌套数组序列化差异:你提到
src的单元格存储的是列表,Streamlit传递Bokeh的ColumnDataSource时,嵌套列表可能被序列化为类数组对象而非标准JS数组,导致Bokeh识别为非可迭代类型。
修复方案
- 替换
var为块级作用域的let声明x,提前赋初始值,循环结束后做无匹配校验,无匹配时直接终止回调逻辑。 - 匹配到对应索引后直接跳出循环,避免后续循环意外覆盖
x的值。 - 用
Array.from()包裹赋值的数组,确保传入src2的是标准可迭代JS数组。 - 操作
src2.data前先做判空,避免数据源未初始化的异常。
修改后的回调代码
callback = CustomJS(args=dict(select=select,src=src,src2=src2), code=''' // 提前初始化x,赋无效初始值 let x = -1; const selectVal = Number(select.value); for (let i = 0; i < src.get_length(); i++) { const nme = src.data['nme'][i]; const targetVal = nme === 'L' ? src.data['i.l'][i] : src.data['i.lo'][i]; if (targetVal === selectVal) { x = i; // 匹配到就跳出,避免后续覆盖 break; } } // 无匹配直接终止,避免后续报错 if (x === -1 || !src2.data) return; // 用Array.from确保是标准数组,兼容序列化差异 src2.data['mean'] = Array.from(src.data['mean'][x]); src2.data['10'] = Array.from(src.data['10'][x]); src2.data['90'] = Array.from(src.data['90'][x]); src2.change.emit(); ''')
内容的提问来源于stack exchange,提问作者amstergc20
相关产品推荐
相关产品推荐

