ipywidgets clear_output() does not work the second time it's used

Viewed 1640

I am experiencing a weird behavior with the Output widget from ipywidgets. I replicate it with the below code in a jupyter notebook:

import ipywidgets as widgets

def clear_output():
    change_output_button = widgets.Button(description="Change output?")
    the_output = widgets.Output()
    clear_output_widget = widgets.VBox([change_output_button, the_output])
    clear_output_widget.click_count = 0

    def button_clicked(_button):
        clear_output_widget.click_count += 1
        the_output.clear_output()
        the_output.append_stdout(f"button clicked {clear_output_widget.click_count} times.")

    change_output_button.on_click(button_clicked)

    return clear_output_widget

In another cell, I input

clear_output()

which displays the button as intended.

Below are the sequence of outputs I get:

  • click 1
button clicked 1 times.
  • click 2
button clicked 1 times.button clicked 2 times.
  • click 3
button clicked 3 times.
  • click 4
button clicked 4 times.

and so on...

I do not understand the click 2 behavior. Am I doing something wrong?

Below is my About Jupyter Notebook info:

Server Information: You are using Jupyter notebook.

The version of the notebook server is: 6.0.1 The server is running on this version of Python:

Python 3.7.4 (default, Aug  9 2019, 18:22:51) [MSC v.1915 32 bit (Intel)]

Current Kernel Information:

Python 3.7.4 (default, Aug  9 2019, 18:22:51) [MSC v.1915 32 bit (Intel)]
Type 'copyright', 'credits' or 'license' for more information
IPython 7.8.0 -- An enhanced Interactive Python. Type '?' for help.

Thanks for you help!

1 Answers

It seems to be due to using append_stdout rather than the context manager. Probably a buffering problem.

In the meantime you can do:

import ipywidgets as widgets


def clear_output():
    change_output_button = widgets.Button(description="Change output?")
    the_output = widgets.Output()
    clear_output_widget = widgets.VBox([change_output_button, the_output])
    clear_output_widget.click_count = 0

    def button_clicked(_button):
        clear_output_widget.click_count += 1
        the_output.clear_output()
        with the_output:
            print(f"button clicked {clear_output_widget.click_count} times.")


    change_output_button.on_click(button_clicked)

    return clear_output_widget
Related