在IPython/Jupyter Notebook线程中调用display渲染HTML报错求助
在IPython Notebook子线程中使用display方法报错的解决办法
你遇到的问题很典型——IPython的display API不是线程安全的,它依赖于主线程的IPython上下文环境,直接在子线程里调用会因为缺少必要的运行上下文抛出异常。
先看看你的代码:
def foo(): display(HTML('<div id="foobar">foobarbaz</div>')) threading.Thread(target=foo).start()
对应的错误信息:
Exception in thread Thread-17: Traceback (most recent call last): File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner self.run() File "/usr/lib/python3.5/threading.py", line 862, in run self._target(*self._args, **self._kwargs) File "<...>
下面给你两种可行的解决思路:
方法一:借助IPython的主线程调用API
IPython内核提供了invoke_in_main_thread方法,可以把需要执行的display操作调度到主线程中运行,这样就能获取到必要的上下文了:
import threading from IPython.display import display, HTML def foo(): # 先创建HTML对象 html_content = HTML('<div id="foobar">foobarbaz</div>') # 调用主线程执行display get_ipython().kernel.invoke_in_main_thread(display, html_content) threading.Thread(target=foo).start()
方法二:使用ipywidgets的Output组件
如果你已经在使用ipywidgets,Output组件是线程安全的,可以通过它的上下文管理器在子线程中安全输出内容:
import threading from IPython.display import display, HTML from ipywidgets import Output # 先在主线程创建并显示Output组件 output_widget = Output() display(output_widget) def foo(): # 使用Output的上下文管理器包裹display操作 with output_widget: display(HTML('<div id="foobar">foobarbaz</div>')) threading.Thread(target=foo).start()
这两种方法都能解决子线程中调用display报错的问题,你可以根据自己的场景选择合适的方式~
内容的提问来源于stack exchange,提问作者kotakotakota




