Bokeh: 模型必须只属于单个文档

22

我正在使用Jupyter笔记本与Bokeh 0.12.2一起工作,经常会出现关于“模型必须仅由一个文档拥有”的异常:

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-23-f50ac7abda5e> in <module>()
      2     ea.legend.label_text_font_size = '10pt'
      3 
----> 4 show(column([co2, co, nox, o3]))

C:\Users\pokeeffe\AppData\Local\Continuum\Anaconda3\lib\site-packages\bokeh\io.py in show(obj, browser, new, notebook_handle)
    308     '''
    309     if obj not in _state.document.roots:
--> 310         _state.document.add_root(obj)
    311     return _show_with_state(obj, _state, browser, new, notebook_handle=notebook_handle)
    312 

C:\Users\pokeeffe\AppData\Local\Continuum\Anaconda3\lib\site-packages\bokeh\document.py in add_root(self, model)
    443             self._roots.append(model)
    444         finally:
--> 445             self._pop_all_models_freeze()
    446         self._trigger_on_change(RootAddedEvent(self, model))
    447 

C:\Users\pokeeffe\AppData\Local\Continuum\Anaconda3\lib\site-packages\bokeh\document.py in _pop_all_models_freeze(self)
    343         self._all_models_freeze_count -= 1
    344         if self._all_models_freeze_count == 0:
--> 345             self._recompute_all_models()
    346 
    347     def _invalidate_all_models(self):

C:\Users\pokeeffe\AppData\Local\Continuum\Anaconda3\lib\site-packages\bokeh\document.py in _recompute_all_models(self)
    367             d._detach_document()
    368         for a in to_attach:
--> 369             a._attach_document(self)
    370         self._all_models = recomputed
    371         self._all_models_by_name = recomputed_by_name

C:\Users\pokeeffe\AppData\Local\Continuum\Anaconda3\lib\site-packages\bokeh\model.py in _attach_document(self, doc)
     89         '''This should only be called by the Document implementation to set the document field'''
     90         if self._document is not None and self._document is not doc:
---> 91             raise RuntimeError("Models must be owned by only a single document, %r is already in a doc" % (self))
     92         doc.theme.apply_to_model(self)
     93         self._document = doc

RuntimeError: Models must be owned by only a single document, <bokeh.models.tickers.DaysTicker object at 0x00000000042540B8> is already in a doc

触发器总是调用show(...)(尽管在内核启动后的第一次调用时不会,只有随后的调用才会执行)。

根据文档,我以为reset_output()会将我的笔记本恢复到可操作状态,但异常仍然存在。通过试错,我已经确定还需要重新定义传递给show()的所有内容。这使得交互式工作变得繁琐且容易出错。

[引用]:

reset_output(state=None)

  清除所有输出模式的默认状态。

  返回值: None


  • 我对reset_output()的理解正确吗 -- 它是否应该解决导致此异常的情况?

  • 否则,我该如何避免这种异常?


我的第一个建议是升级。 Bokeh和Notebook都是非常大的,跨运行时的东西,将它们集成在一起是持续改进的挑战。我知道自从0.12.2以来有些工作已经完成,尽管我没有时间去研究细节。否则,请发布完整的代码示例以进行检查/尝试。例如,我知道多次显示相同的图表是可以正常工作的(我只是为了确认而尝试了),因此如果没有测试笔记本来重现该问题,则无法猜测您的具体问题是什么。 - bigreddot
7个回答

6

可能是因为存在具有相同名称的冲突对象。您需要每次创建全新的对象。


5
我一直在使用jupyterlab笔记本迭代大量数据的可视化,使用bokeh、holoviews和panel,但不时遇到此问题。
下面是几个可能有帮助的细节。请注意,p被用作bokeh习惯性的图形名称。我在这个旧的线程上发布,因为它是我在Google搜索中找到的错误信息的最佳结果之一。
尝试清除文档(在文档中可以找到)。
from bokeh.io import curdoc

curdoc().clear()

我注意到 Panel 可以展示 Bokeh 对象,即使 Bokeh show 不能。
import panel as pn

pn.extension()

pn.pane.Bokeh(p)

深入研究了一下,发现在bokeh无法显示对象的情况下,panel是如何实现显示对象的。我注意到这个函数,它解决了我的问题。
import panel as pn

pn.io.model.remove_root(p)

如果您尚未安装面板,这里是上述代码的源代码:

from bokeh.models import Model

for model in p.select({'type': Model}):
    prev_doc = model.document
    model._document = None
    if prev_doc:
        prev_doc.remove_root(model)

希望这能对某人有所帮助,或者对未来的我有用。

4
这个解决方案无需升级或降级软件包即可实现。
try:
    reset_output()
    output_notebook()
    show(p)
except:
    output_notebook()
    show(p)

这里提供的解决方案是: https://github.com/bokeh/bokeh/issues/8579

4
似乎可以通过区分源名称来修复它,就像这样:

source1 = df
p1.circle('A', 'B', source=source1)

source2 = df
p2 = figure()
p2.circle('C', 'D', source=source2)

sourceN = df
p2 = figure()
p2.circle('X', 'Y', source=sourceN)

2

我在使用bokeh.embed的file_html时遇到了这个错误信息,升级到bokeh版本1.01后出现了这个问题。将bokeh版本降级到0.12.16后问题得到解决。(pip install bokeh==0.12.16) 不确定原因。


1
从1.0.1版本降级到0.13.0版本解决了我的问题。 - ic_fl2

0
column_data_source = ColumnDataSource(dataframe)

在使用列数据源的Jupyter笔记本中,每行后面我们都必须再次简单地制作它。列数据源似乎不能在同一代码中多次使用。
这似乎有点hack,但当我遇到相同错误时,它对我起了作用。

0

在创建每个图之后尝试使用。 add_root 将该模型添加为当前文档的根,确保每个模型都添加到单个文档中:

    curdoc().add_root(column([plot]))
    curdoc().title = doc_title //Add a title to the doc
    show(figure)

注意:column(图表列表)可以替换为任何继承Model类的对象。

有关add_root和bokeh文档的更多详细信息,请参阅以下链接:https://docs.bokeh.org/en/latest/docs/reference/document.html?highlight=add_root#bokeh.document.document.Document.add_root


1
欢迎来到 StackOverFlow,请您详细说明您的答案如何实现问题的要求以及与其他提议的答案相比有何优劣之处? - Mike

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接