在运行异步递归函数时,如何使用异步Python允许Jupyter按钮小部件单击进行处理?

2024-10-02 00:33:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我设置了一个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中,注意我决定在一个单独的块中执行此操作,因为我使用animatefunc执行的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,并尝试使用异步休眠,但按钮的事件循环似乎仍然被锁定


Tags: 代码selftrueoutputdefdisplayjupyter动画

热门问题