显示输出到日志窗口而不是 Jupyter Lab 中的单元格

问题描述 投票:0回答:1

我有一个 jupyter 实验室脚本,我想在其中运行 for 循环,对于每次迭代,我想显示一些信息,然后根据这些信息决定是否执行某些操作(创建符号链接)。理想情况下,我会通过单击“是”选项来使用小部件 ToggleButtons,或者单击“跳过”选项(如果我不想执行该操作)。我认为这些细节并不重要,但如果您需要了解更多信息,请告诉我。要点是,我想在每次迭代的单元格输出中显示的 ToggleButtons 小部件仅在第一次迭代时显示。对于下一次迭代,它会进入日志。我怎样才能改变这一点?如果我无法显示小部件,我就无法将我的决定告知脚本。通过查看日志,很明显我可以跳到下一个迭代直到循环结束。

我创建了一个重现该问题的示例:




from functools import wraps
import ipywidgets as widgets

def yield_for_button(widget, attribute):
#https://ipywidgets.readthedocs.io/en/7.6.5/examples/Widget%20Asynchronous.html    
    """Pause a generator to wait for a widget change event.

    This is a decorator for a generator function which pauses the generator on yield
    until the given widget attribute changes. The new value of the attribute is
    sent to the generator and is the value of the yield.
    """
    def f(iterator):
        @wraps(iterator)
        def inner():
            i = iterator()
            def next_i(change):
                try:
                    i.send(change.new)
                except StopIteration as e:
                    widget.unobserve(next_i, attribute)
            widget.observe(next_i, attribute)
            # start the generator
            next(i)
        return inner
    return f



#df_redcap = DefaultRedcapConnector().get_dataframe(raw_or_label="raw")
button=widgets.ToggleButton(
    value=False,
    description='Go to next!',
    disabled=False,
    button_style='', # 'success', 'info', 'warning', 'danger' or ''
    tooltip='Description',
    icon='check' # (FontAwesome names without the `fa-` prefix)
)

def on_button_clicked(*args,**kwargs):
    print("Button clicked.")

names = ['fabio', 'gaia', 'matteo', 'luca', 'eva']    
    
@yield_for_button(button, 'value')
def f():            
    for name in names:
        print(name)
        a = widgets.HTML(
            value = '<b>Like this name?</b><br>' ,
            placeholder='Some HTML',
            description='',
            disabled=True
        )

        c = widgets.ToggleButtons(
            options=['Yes', 'Skip', 'Stop'],
            value='Stop',
            description='Action to perform:'
        ) 

        z = widgets.VBox([a,c,button], layout=Layout(height='200px', overflow_y='auto'))

        display(z)


        action = yield
        #button.on_click(on_button_clicked)

        if c.value == 'Yes':
            print('I agree it s a nice name.')
        else:
            None
        #c.value = 'Stop'    


f()

我的jupyter lab版本是:3.5.1(我似乎记得在以前的版本中代码运行没有问题)。 这个问题与this one类似,但我无法通过使其适应我的问题来解决我的问题(即将显示放在 with 指令中)。

widget jupyter-lab togglebutton
1个回答
0
投票

这更接近您需要做的事情:

from functools import wraps
import ipywidgets as widgets

output = widgets.Output()

def yield_for_button(widget, attribute):
#https://ipywidgets.readthedocs.io/en/7.6.5/examples/Widget%20Asynchronous.html    
    """Pause a generator to wait for a widget change event.

    This is a decorator for a generator function which pauses the generator on yield
    until the given widget attribute changes. The new value of the attribute is
    sent to the generator and is the value of the yield.
    """
    def f(iterator):
        @wraps(iterator)
        def inner():
            i = iterator()
            def next_i(change):
                try:
                    i.send(change.new)
                except StopIteration as e:
                    widget.unobserve(next_i, attribute)
            widget.observe(next_i, attribute)
            # start the generator
            next(i)
        return inner
    return f



#df_redcap = DefaultRedcapConnector().get_dataframe(raw_or_label="raw")
button=widgets.ToggleButton(
    value=False,
    description='Go to next!',
    disabled=False,
    button_style='', # 'success', 'info', 'warning', 'danger' or ''
    tooltip='Description',
    icon='check' # (FontAwesome names without the `fa-` prefix)
)

def on_button_clicked(*args,**kwargs):
    with output:
        print("Button clicked.")

names = ['fabio', 'gaia', 'matteo', 'luca', 'eva']    
    
@yield_for_button(button, 'value')
def f():            
    for name in names:
        with output:
            print(name)
        a = widgets.HTML(
            value = '<b>Like this name?</b><br>' ,
            placeholder='Some HTML',
            description='',
            disabled=True
        )

        c = widgets.ToggleButtons(
            options=['Yes', 'Skip', 'Stop'],
            value='Stop',
            description='Action to perform:'
        ) 

        z = widgets.VBox([a,c,button], layout=widgets.Layout(height='200px', overflow_y='auto'))

        with output:
            display(z)


        action = yield
        #button.on_click(on_button_clicked)

        if c.value == 'Yes':
            with output:
                print('I agree it s a nice name.')
        else:
            pass
        #c.value = 'Stop'    


display(f(), output);

我无法弄清楚第一个显示的“

None
”来自哪里,但目前这在 JupyterLab 和 Jupyter Notebook(NbClassic 和 Jupyter Notbeook 7+)中都有效。

© www.soinside.com 2019 - 2024. All rights reserved.