Output
Capture
import ipywidgets as widgets

# define components
debug_view = widgets.Output(layout={'border': '1px solid black'})

button = widgets.Button(description='Click',layout={'width': '300px'})

# callback
@debug_view.capture(clear_output=True)
def bad_callback(event):
    print('This is about to explode')

# event
button.on_click(bad_callback)

# layout
widgets.VBox([button, debug_view])
		
Output
import ipywidgets as widgets

# define components
debug_view = widgets.Output(layout={'border': '1px solid black'})

button = widgets.Button(description='Click',layout={'width': '300px'})

# callback
def bad_callback(event):
    with debug_view:
        print('This is about to explode')

# event
button.on_click(bad_callback)

# layout
widgets.VBox([button, debug_view])
        
Append
# append_stdout, append_stderr, or append_display_data
from IPython.display import YouTubeVideo
out = widgets.Output(layout={'border': '1px solid black'})
out.append_stdout('Output appended with append_stdout\n')
out.append_stderr('Output appended with append_stdout')
out.append_display_data(YouTubeVideo('eWzY2nGfkXk'))

display(out)
        
Threading
import threading
from IPython.display import display, HTML
import ipywidgets as widgets
import datetime
import time

out = widgets.Output()
#out_html = widgets.HTML(layout={'border':'1px solid red'})
display(out)

def thread_func():
    while True:
        time.sleep(1)
        with out:
            out.clear_output()
            print(datetime.datetime.now().time())
        
thread = threading.Thread(target=thread_func,)
thread.start()