Jupyter 中的非阻塞单元执行

Ban*_*ach 6 ipython jupyter-notebook ipywidgets

在具有 ipython 内核的 Jupyter 中,是否有一种规范的方法以非阻塞方式执行单元?

理想情况下,我希望能够运行一个单元格

%%background
time.sleep(10)
print("hello")
Run Code Online (Sandbox Code Playgroud)

这样我就可以开始编辑和运行下一个单元格,并在 10 秒内看到“hello”出现在原始单元格的输出中。


我尝试了两种方法,但都不满意。

(1) 手动创建线程:

def foo():
    time.sleep(10)
    print("hello")
threading.Thread(target=foo).start()
Run Code Online (Sandbox Code Playgroud)

这样做的问题是,“hello”会在 10 秒内处于活动状态的任何单元格中打印,而不一定在启动线程的单元格中打印。

(2) 使用ipywidget.Output小部件。

def foo(out):
    time.sleep(10)
    out.append_stdout("hello")
out = ipywidgets.Output()
display(out)
threading.Thread(target=foo,args=(out,)).start()
Run Code Online (Sandbox Code Playgroud)

这是可行的,但是当我想更新输出时会出现问题(考虑监视内存消耗等内容):

def foo(out):
    while True:
        time.sleep(1)
        out.clear_output()
        out.append_stdout(str(datetime.datetime.now()))
out = ipywidgets.Output()
display(out)
threading.Thread(target=foo,args=(out,)).start()
Run Code Online (Sandbox Code Playgroud)

现在输出的大小不断在 0 行和 1 行之间切换,这导致整个笔记本电脑闪烁。

这应该可以wait=True在调用中解决clear_output。唉,对我来说,这导致输出永远不会显示任何内容。

我本可以询问这个问题,具体来说,这似乎是一个错误,但我想知道是否有另一种解决方案不需要我手动完成所有这些工作。

ac2*_*c24 0

我在绘制输出时遇到了一些类似的问题,看起来您已经遵循了 ipywidgets 文档中有关异步输出小部件的示例。

我发现有时有用的另一种方法(特别是如果您知道所需输出的大小)是在创建输出小部件时固定它的高度。

out = ipywidgets.Output(layout=ipywidgets.Layout(height='25px'))