我设置了一个Jupyter笔记本,在那里我运行一个递归函数,可以像这样清除输出,创建一个动画输出:
from IPython.display import clear_output
active = True
def animate:
myOutput = ""
# do stuff
clear_output(wait=True)
print(myOutput)
sleep(0.2)
if active:
animate()
这是完美的工作
但现在我想再添加一个步骤:速度切换。我制作的动画是一个调试可视化,光标在解释代码中移动,我编写的解释器解析该代码。我尝试了条件减速,以便在解析继续时有更多的时间阅读正在发生的事情,但我真正需要的是能够单击按钮在快速和慢速之间切换速度。也许我会使用一个滑块,但现在我只想要一个用于概念验证的按钮
这听起来很简单。请注意,我将其作为一个类进行有状态编写,因为我需要从另一个导入的类中读取/写入状态
Jupyter 1区:
import ipywidgets as widgets
from IPython.display import display
out = widgets.Output()
class ToggleState():
def __init__(self):
self.button = widgets.Button(description="Toggle")
self.button.on_click(self.toggle)
display(self.button)
self.toggleState = False
print("Toggle State:", self.toggleState)
def toggle(self, arg): # arg has to be accepted here to meet on_click requirements
self.toggleState = not self.toggleState
print("Toggle State:", self.toggleState)
def read(self):
return self.toggleState
toggleState = ToggleState()
然后,在Jupyter block 2中,注意我决定在一个单独的块中执行此操作,因为我使用animate
func执行的clear_输出会清除位于同一块中的按钮,这就是问题所在:
active = True
def animate:
myOutput = ""
# do stuff
clear_output(wait=True)
print(myOutput)
if toggleState.read():
sleep(5)
else:
sleep(0.2)
if active:
animate()
但这种方法的问题是,两个块实际上不是同时运行的(没有使用并行内核,这比我所关心的要复杂得多),因此button无法继续接收前一个块中的输入。现在看起来很明显,但我没想过
如何以不删除按钮的方式清除输入(以便将按钮放入动画块)
编辑:
我以为我找到了解决办法,但只是其中的一部分:
使用^{
out = widgets.Output()
及
with out:
clear_output(wait=True) # clears only the logged output
# logging code
我们可以在同一块中渲染为两个独立的标准输出。这在一定程度上起作用,如在动画渲染中,按钮未清除。但当动画循环运行时,按钮似乎无法处理输入。因此,它看起来确实像是一个同步代码/事件循环阻塞问题。这里有什么问题
我是否需要释放事件循环的sleep
替代方案
编辑2:
在用Python搜索异步代码之后,我了解了asyncio
,但我仍在努力。Jupyter已经通过asyncio.run()
运行代码,但是组件显然必须定义为async
才能起作用。我将animate
定义为async
,并尝试使用异步休眠,但按钮的事件循环似乎仍然被锁定
目前没有回答
相关问题 更多 >
编程相关推荐