ipywidgets
ipywidgets copied to clipboard
Output widget's clear_output not clearing when using append_stdout
I stumbled upon a question on Stack Overflow where the first line printed in the output widget doesn't get cleared by the first call to clear_output
.
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`
Replacing append_stdout
with the context manager fixes the issue:
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.")
but I am unsure of the reasons behind the erratic behaviour. I tried to look at the source of append_stdout
but I haven't found it so far. Happy to submit a PR once I get to the bottom of this issue.
Hi, is there an update?
Following code does not work:
import asyncio
import threading
from IPython.display import display, HTML
import ipywidgets as widgets
import time
SLEEP = 1
all_tasks = asyncio.all_tasks()
for task in all_tasks:
task.cancel()
async def do(out):
while True:
await asyncio.sleep(SLEEP)
out.append_display_data(HTML("<em>All done!</em>"))
out.clear_output()
out = widgets.Output()
# Now the key: the container is displayed (while empty) in the main thread
display(out)
asyncio.create_task(do(out));
Not working means the output is not cleared :nerd_face:
As mentioned on stackoverflow, clear_output is using Jupyter's display mechanism, and is the same as:
import IPython.display
with clear_output_widget:
IPython.display.clear_output()
append_stdout is not using the display mechanism, but the context manager is.
I think there is room for improvement here, since now the Output widget is mixing two things (display mechanism and state syncing). I think we should be more consistent, use both, or one of them. We cannot avoid the display mechanism since that would not play nice with clear_display(wait=True)
. I would be in favor of using both, so the widget is always in a consistent state, even without a frontend connected.
This means that a frontend:
- will initially first just display whatever
outputs
state is. - It reacts to changes in display/clear_output.
- Changes to outputs are immediate, they do no respect clear_output.
Hi!
I did have the same issue. But turned out that I could not even use the context manager, as I was trying to clear / update the Output from a thread, so that my notebook would still be available, and the output would update with data from rest calls.
And that does not work very well. I assume that the with out:
is using some static variable that don't play well with threading.
I worked around it by using a out = widgets.HTML()
and calling out.value = f"<pref>{my_message}</pre>"
in the thread function.
I'm wondering if @wonsjb's workaround works if I'm already using the workaround with show_inline_matplotlib_plots()
: https://github.com/jupyter-widgets/ipywidgets/issues/1853#issuecomment-349201240
workaround for this is posted on another thread: https://github.com/jupyter-widgets/ipywidgets/issues/3260#issuecomment-907715980