Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Output widget's clear_output not clearing when using append_stdout #2584

Open
jagaudin opened this issue Oct 15, 2019 · 5 comments
Open

Output widget's clear_output not clearing when using append_stdout #2584

jagaudin opened this issue Oct 15, 2019 · 5 comments

Comments

@jagaudin
Copy link

jagaudin commented Oct 15, 2019

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.

@katsar0v
Copy link

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 🤓

@maartenbreddels
Copy link
Member

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.

@wonsjb
Copy link

wonsjb commented Oct 9, 2020

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.

@StefanBrand
Copy link
Contributor

I'm wondering if @wonsjb's workaround works if I'm already using the workaround with show_inline_matplotlib_plots(): #1853 (comment)

@pnsvk
Copy link

pnsvk commented Mar 15, 2022

workaround for this is posted on another thread: #3260 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants