diff --git a/docs/source/examples/Output Widget.ipynb b/docs/source/examples/Output Widget.ipynb new file mode 100644 index 0000000000..f0a1899071 --- /dev/null +++ b/docs/source/examples/Output Widget.ipynb @@ -0,0 +1,875 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "nbsphinx": "hidden" + }, + "source": [ + "[Index](Index.ipynb) - [Back](Widget List.ipynb) - [Next](Widget Events.ipynb)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Output widgets: leveraging Jupyter's display system" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import ipywidgets as widgets" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "The `Output` widget can capture and display stdout, stderr and [rich output generated by IPython](http://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#module-IPython.display). You can also append output directly to an output widget, or clear it programmatically." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "a269be447b494cc3a8fa6332fefda978", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output(layout=Layout(border='1px solid black'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "out = widgets.Output(layout={'border': '1px solid black'})\n", + "out" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "After the widget is created, direct output to it using a context manager. You can print text to the output area:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "with out:\n", + " for i in range(10):\n", + " print(i, 'Hello world!')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Rich output can also be directed to the output area. Anything which displays nicely in a Jupyter notebook will also display well in the `Output` widget." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import YouTubeVideo\n", + "with out:\n", + " display(YouTubeVideo('eWzY2nGfkXk'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can even display complex mimetypes, such as nested widgets, in an output widget." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "with out:\n", + " display(widgets.IntSlider())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also append outputs to the output widget directly with the convenience methods `append_stdout`, `append_stderr`, or `append_display_data`." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d0b8a41678e34cbb95bfd03895d5b205", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output(layout=Layout(border='1px solid black'), outputs=({'output_type': 'stream', 'name': 'stdout', 'text': '..." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "out = widgets.Output(layout={'border': '1px solid black'})\n", + "out.append_stdout('Output appended with append_stdout')\n", + "out.append_display_data(YouTubeVideo('eWzY2nGfkXk'))\n", + "out" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that `append_display_data` cannot currently be used to display widgets. The status of this bug is tracked in [this issue](https://github.com/jupyter-widgets/ipywidgets/issues/1811)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can clear the output by either using `IPython.display.clear_output` within the context manager, or we can call the widget's `clear_output` method directly." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "out.clear_output()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`clear_output` supports the keyword argument `wait`. With this set to `True`, the widget contents are not cleared immediately. Instead, they are cleared the next time the widget receives something to display. This can be useful when replacing content in the output widget: it allows for smoother transitions by avoiding a jarring resize of the widget following the call to `clear_output`.\n", + "\n", + "Finally, we can use an output widget to capture all the output produced by a function using the `capture` decorator." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "@out.capture()\n", + "def function_with_captured_output():\n", + " print('This goes into the output widget')\n", + " raise Exception('As does this')\n", + " \n", + "function_with_captured_output()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`out.capture` supports the keyword argument `clear_output`. Setting this to `True` will clear the output widget every time the function is invoked, so that you only see the output of the last invocation. With `clear_output` set to `True`, you can also pass a `wait=True` argument to only clear the output once new output is available." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Output widgets as the foundation for interact\n", + "\n", + "The output widget forms the basis of how interact and related methods are implemented. It can also be used by itself to create rich layouts with widgets and code output. One simple way to customize how an interact UI looks is to use the `interactive_output` function to hook controls up to a function whose output is captured in the returned output widget. In the next example, we stack the controls vertically and then put the output of the function to the right." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "681b180038d147c5b18698d6ed2dcd80", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HBox(children=(VBox(children=(IntSlider(value=0, description='a'), IntSlider(value=0, description='b'), IntSli..." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "a = widgets.IntSlider(description='a')\n", + "b = widgets.IntSlider(description='b')\n", + "c = widgets.IntSlider(description='c')\n", + "def f(a, b, c):\n", + " print('{}*{}*{}={}'.format(a, b, c, a*b*c))\n", + "\n", + "out = widgets.interactive_output(f, {'a': a, 'b': b, 'c': c})\n", + "\n", + "widgets.HBox([widgets.VBox([a, b, c]), out])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Debugging errors in callbacks with the output widget\n", + "\n", + "On some platforms, like JupyterLab, output generated by widget callbacks (for instance, functions attached to the `.observe` method on widget traits, or to the `.on_click` method on button widgets) are not displayed anywhere. Even on other platforms, it is unclear what cell this output should appear in. This can make debugging errors in callback functions more challenging. \n", + "\n", + "An effective tool for accessing the output of widget callbacks is to decorate the callback with an output widget's capture method. You can then display the widget in a new cell to see the callback output." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "cbd3717edd3b4a62b057b7fa3725bbdb", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Button(description='click me to raise an exception', layout=Layout(width='300px'), style=ButtonStyle())" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "debug_view = widgets.Output(layout={'border': '1px solid black'})\n", + "\n", + "@debug_view.capture(clear_output=True)\n", + "def bad_callback(event):\n", + " print('This is about to explode')\n", + " return 1.0 / 0.0\n", + "\n", + "button = widgets.Button(\n", + " description='click me to raise an exception',\n", + " layout={'width': '300px'}\n", + ")\n", + "button.on_click(bad_callback)\n", + "button" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "031240f0fb3048188600bb2a404aa78b", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output(layout=Layout(border='1px solid black'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "debug_view" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Integrating output widgets with the logging module\n", + "\n", + "While using the `.capture` decorator works well for understanding and debugging single callbacks, it does not scale to larger applications. Typically, in larger applications, one might use the [logging](https://docs.python.org/3/library/logging.html) module to print information on the status of the program. However, in the case of widget applications, it is unclear where the logging output should go.\n", + "\n", + "A useful pattern is to create a custom [handler](https://docs.python.org/3/library/logging.html#handler-objects) that redirects logs to an output widget. The output widget can then be displayed in a new cell to monitor the application while it runs." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "import ipywidgets as widgets\n", + "import logging\n", + "\n", + "class OutputWidgetHandler(logging.Handler):\n", + " \"\"\" Custom logging handler sending logs to an output widget \"\"\"\n", + "\n", + " def __init__(self, *args, **kwargs):\n", + " super(OutputWidgetHandler, self).__init__(*args, **kwargs)\n", + " layout = {\n", + " 'width': '100%', \n", + " 'height': '160px', \n", + " 'border': '1px solid black'\n", + " }\n", + " self.out = widgets.Output(layout=layout)\n", + "\n", + " def emit(self, record):\n", + " \"\"\" Overload of logging.Handler method \"\"\"\n", + " formatted_record = self.format(record)\n", + " new_output = {\n", + " 'name': 'stdout', \n", + " 'output_type': 'stream', \n", + " 'text': formatted_record+'\\n'\n", + " }\n", + " self.out.outputs = (new_output, ) + self.out.outputs\n", + " \n", + " def show_logs(self):\n", + " \"\"\" Show the logs \"\"\"\n", + " display(self.out)\n", + " \n", + " def clear_logs(self):\n", + " \"\"\" Clear the current logs \"\"\"\n", + " self.out.clear_output()\n", + "\n", + "\n", + "logger = logging.getLogger(__name__)\n", + "handler = OutputWidgetHandler()\n", + "handler.setFormatter(logging.Formatter('%(asctime)s - [%(levelname)s] %(message)s'))\n", + "logger.addHandler(handler)\n", + "logger.setLevel(logging.INFO)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "9d016f4f8558496091a0a8bfc0c8a563", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output(layout=Layout(border='1px solid black', height='160px', width='100%'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "handler.show_logs()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "handler.clear_logs()\n", + "logger.info('Starting program')\n", + "\n", + "try:\n", + " logger.info('About to try something dangerous...')\n", + " 1.0/0.0\n", + "except Exception as e:\n", + " logger.exception('An error occurred!')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Interacting with output widgets from background threads\n", + "\n", + "Jupyter's `display` mechanism can be counter-intuitive when displaying output produced by background threads. A background thread's output is printed to whatever cell the main thread is currently writing to. To see this directly, create a thread that repeatedly prints to standard out:\n", + "\n", + "```python\n", + "import threading\n", + "import time\n", + "\n", + "def run():\n", + " for i in itertools.count(0):\n", + " time.sleep(1)\n", + " print('output from background {}'.format(i))\n", + " \n", + "t = threading.Thread(target=run)\n", + "t.start()\n", + "```\n", + "\n", + "This always prints in the currently active cell, not the cell that started the background thread.\n", + "\n", + "This can lead to surprising behaviour in output widgets. During the time in which output is captured by the output widget, *any* output generated in the notebook, regardless of thread, will go into the output widget.\n", + "\n", + "The best way to avoid surprises is to *never* use an output widget's context manager in a context where multiple threads generate output. Instead, we can pass an output widget to the function executing in a thread, and use `append_display_data()`, `append_stdout()`, or `append_stderr()` methods to append displayable output to the output widget." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Display in main thread'" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6c5a6d9e95c64b19b0829d62d6a3d142", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import threading\n", + "from IPython.display import display, HTML\n", + "import ipywidgets as widgets\n", + "import time\n", + "\n", + "def thread_func(something, out):\n", + " for i in range(1, 5):\n", + " time.sleep(0.3)\n", + " out.append_stdout('{} {} {}\\n'.format(i, '**'*i, something))\n", + " out.append_display_data(HTML(\"All done!\"))\n", + "\n", + "display('Display in main thread')\n", + "out = widgets.Output()\n", + "# Now the key: the container is displayed (while empty) in the main thread\n", + "display(out)\n", + "\n", + "thread = threading.Thread(\n", + " target=thread_func,\n", + " args=(\"some text\", out))\n", + "thread.start()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": { + "031240f0fb3048188600bb2a404aa78b": { + "model_module": "@jupyter-widgets/output", + "model_module_version": "1.0.0", + "model_name": "OutputModel", + "state": { + "layout": "IPY_MODEL_eb7440e7cb654ef1b81456201ad73046" + } + }, + "09ebae74114e4d0ebddc76ea7d0b229e": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.0.0", + "model_name": "LayoutModel", + "state": {} + }, + "1db1e906e17b41a6ba21bce7913153e1": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.1.0", + "model_name": "SliderStyleModel", + "state": { + "description_width": "" + } + }, + "20f7d695b1d546aa9dd0aff8f97cc68d": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.1.0", + "model_name": "IntSliderModel", + "state": { + "description": "a", + "layout": "IPY_MODEL_5f93e1548a9c4122ad88f8571b089bff", + "style": "IPY_MODEL_f293dd82b7cf4c62ab33fb92e6dbbfd0" + } + }, + "28a2252ef4f94aadb035d7a89859bbf4": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.0.0", + "model_name": "LayoutModel", + "state": {} + }, + "2ccf6ff212c549b0b79c1830dd2c32ee": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.1.0", + "model_name": "IntSliderModel", + "state": { + "layout": "IPY_MODEL_bf69db584eb24270b597915d6da60aad", + "style": "IPY_MODEL_9a33f2faeb044ee683d04c107804b0fa" + } + }, + "2f6ced63c0064ca99c235579b3149c77": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.1.0", + "model_name": "SliderStyleModel", + "state": { + "description_width": "" + } + }, + "32e3079f5723492c9fe5d28455254d36": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.0.0", + "model_name": "LayoutModel", + "state": {} + }, + "3701ff1794154c8786292f3b387f3ef8": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.0.0", + "model_name": "LayoutModel", + "state": { + "border": "1px solid black" + } + }, + "54707ea3a8eb40ea8dcd631e52598f49": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.0.0", + "model_name": "LayoutModel", + "state": { + "border": "1px solid black", + "height": "160px", + "width": "100%" + } + }, + "59a60fe94d264eaa9cb7e0860254966e": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.0.0", + "model_name": "LayoutModel", + "state": {} + }, + "5f93e1548a9c4122ad88f8571b089bff": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.0.0", + "model_name": "LayoutModel", + "state": {} + }, + "635eca27ab444f0c9517b4854c090a7b": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.1.0", + "model_name": "IntSliderModel", + "state": { + "description": "b", + "layout": "IPY_MODEL_32e3079f5723492c9fe5d28455254d36", + "style": "IPY_MODEL_2f6ced63c0064ca99c235579b3149c77" + } + }, + "681b180038d147c5b18698d6ed2dcd80": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.1.0", + "model_name": "HBoxModel", + "state": { + "children": [ + "IPY_MODEL_c28683de9d2445dca45931c10948f9e3", + "IPY_MODEL_a1934a56f78440059baa4c8afc212d98" + ], + "layout": "IPY_MODEL_df9a09ac807740ec8f99b2fbdd084ca3" + } + }, + "6c5a6d9e95c64b19b0829d62d6a3d142": { + "model_module": "@jupyter-widgets/output", + "model_module_version": "1.0.0", + "model_name": "OutputModel", + "state": { + "layout": "IPY_MODEL_78e11f55caa941488215b077fead6901", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": "1 ** some text\n" + }, + { + "name": "stdout", + "output_type": "stream", + "text": "2 **** some text\n" + }, + { + "name": "stdout", + "output_type": "stream", + "text": "3 ****** some text\n" + }, + { + "name": "stdout", + "output_type": "stream", + "text": "4 ******** some text\n" + }, + { + "data": { + "text/html": "All done!", + "text/plain": "" + }, + "metadata": {}, + "output_type": "display_data" + } + ] + } + }, + "71a64f2556fd45f59be3fcdaa0d5abfd": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.1.0", + "model_name": "ButtonStyleModel", + "state": {} + }, + "78e11f55caa941488215b077fead6901": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.0.0", + "model_name": "LayoutModel", + "state": {} + }, + "9a33f2faeb044ee683d04c107804b0fa": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.1.0", + "model_name": "SliderStyleModel", + "state": { + "description_width": "" + } + }, + "9d016f4f8558496091a0a8bfc0c8a563": { + "model_module": "@jupyter-widgets/output", + "model_module_version": "1.0.0", + "model_name": "OutputModel", + "state": { + "layout": "IPY_MODEL_54707ea3a8eb40ea8dcd631e52598f49", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": "2018-03-28 13:20:45,024 - [ERROR] An error occurred!\nTraceback (most recent call last):\n File \"\", line 6, in \n 1.0/0.0\nZeroDivisionError: float division by zero\n" + }, + { + "name": "stdout", + "output_type": "stream", + "text": "2018-03-28 13:20:45,024 - [INFO] About to try something dangerous...\n" + }, + { + "name": "stdout", + "output_type": "stream", + "text": "2018-03-28 13:20:45,023 - [INFO] Starting program\n" + } + ] + } + }, + "a02c223fcb8545f994e288974c1b1c3d": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.0.0", + "model_name": "LayoutModel", + "state": { + "border": "1px solid black" + } + }, + "a1934a56f78440059baa4c8afc212d98": { + "model_module": "@jupyter-widgets/output", + "model_module_version": "1.0.0", + "model_name": "OutputModel", + "state": { + "layout": "IPY_MODEL_09ebae74114e4d0ebddc76ea7d0b229e", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": "0*0*0=0\n" + } + ] + } + }, + "a269be447b494cc3a8fa6332fefda978": { + "model_module": "@jupyter-widgets/output", + "model_module_version": "1.0.0", + "model_name": "OutputModel", + "state": { + "layout": "IPY_MODEL_3701ff1794154c8786292f3b387f3ef8", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": "0 Hello world!\n1 Hello world!\n2 Hello world!\n3 Hello world!\n4 Hello world!\n5 Hello world!\n6 Hello world!\n7 Hello world!\n8 Hello world!\n9 Hello world!\n" + }, + { + "data": { + "image/jpeg": "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\n", + "text/html": "\n \n ", + "text/plain": "" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "2ccf6ff212c549b0b79c1830dd2c32ee", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": "IntSlider(value=0)" + }, + "metadata": {}, + "output_type": "display_data" + } + ] + } + }, + "bf69db584eb24270b597915d6da60aad": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.0.0", + "model_name": "LayoutModel", + "state": {} + }, + "c28683de9d2445dca45931c10948f9e3": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.1.0", + "model_name": "VBoxModel", + "state": { + "children": [ + "IPY_MODEL_20f7d695b1d546aa9dd0aff8f97cc68d", + "IPY_MODEL_635eca27ab444f0c9517b4854c090a7b", + "IPY_MODEL_ca6fd5b539a745038edbf165dd28350f" + ], + "layout": "IPY_MODEL_59a60fe94d264eaa9cb7e0860254966e" + } + }, + "c31422b145f24deab38a0d6e82d99545": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.0.0", + "model_name": "LayoutModel", + "state": { + "width": "300px" + } + }, + "ca6fd5b539a745038edbf165dd28350f": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.1.0", + "model_name": "IntSliderModel", + "state": { + "description": "c", + "layout": "IPY_MODEL_28a2252ef4f94aadb035d7a89859bbf4", + "style": "IPY_MODEL_1db1e906e17b41a6ba21bce7913153e1" + } + }, + "cbd3717edd3b4a62b057b7fa3725bbdb": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.1.0", + "model_name": "ButtonModel", + "state": { + "description": "click me to raise an exception", + "layout": "IPY_MODEL_c31422b145f24deab38a0d6e82d99545", + "style": "IPY_MODEL_71a64f2556fd45f59be3fcdaa0d5abfd" + } + }, + "d0b8a41678e34cbb95bfd03895d5b205": { + "model_module": "@jupyter-widgets/output", + "model_module_version": "1.0.0", + "model_name": "OutputModel", + "state": { + "layout": "IPY_MODEL_a02c223fcb8545f994e288974c1b1c3d", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": "This goes into the output widget\n" + }, + { + "ename": "Exception", + "evalue": "As does this", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mException\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m~/oss/ipywidgets/ipywidgets/widgets/widget_output.py\u001b[0m in \u001b[0;36minner\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 99\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mclear_output\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mclear_args\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mclear_kwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 100\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 101\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 102\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0minner\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 103\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mcapture_decorator\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mfunction_with_captured_output\u001b[0;34m()\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mfunction_with_captured_output\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'This goes into the output widget'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'As does this'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0mfunction_with_captured_output\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mException\u001b[0m: As does this" + ] + } + ] + } + }, + "df9a09ac807740ec8f99b2fbdd084ca3": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.0.0", + "model_name": "LayoutModel", + "state": {} + }, + "eb7440e7cb654ef1b81456201ad73046": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.0.0", + "model_name": "LayoutModel", + "state": { + "border": "1px solid black" + } + }, + "f293dd82b7cf4c62ab33fb92e6dbbfd0": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.1.0", + "model_name": "SliderStyleModel", + "state": { + "description_width": "" + } + } + }, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/docs/source/examples/Widget Asynchronous.ipynb b/docs/source/examples/Widget Asynchronous.ipynb index 9d842dd164..6246fb40ca 100644 --- a/docs/source/examples/Widget Asynchronous.ipynb +++ b/docs/source/examples/Widget Asynchronous.ipynb @@ -280,75 +280,6 @@ "thread.start()" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Interacting with output widgets from background threads\n", - "\n", - "Output widgets capture output based on the thread in which they were invoked.\n", - "In other words, in the thread where the output is invoked, there is a context\n", - "manager which starts and then stops the output capturing. If you call `display`\n", - "in a thread other than the thread containing the context manager, you cannot\n", - "rely on those `display` calls being captured by the context manager.\n", - "\n", - "Instead, we can pass an `Output` widget to the function executing in a thread,\n", - "and use the `Output`'s `append_display_data()`, `append_stdout()`, or\n", - "`append_stderr()` methods to append displayable output (such as from `HTML()`),\n", - "standard output (such as from `print()`), or standard error to the `Output`\n", - "widget." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'Display in main thread'" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "32e8e3b06ec44fabb832283d779fda97", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "A Jupyter Widget" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import threading\n", - "from IPython.display import display, HTML\n", - "import ipywidgets as widgets\n", - "\n", - "def thread_func(something, out):\n", - " for i in range(1, 10):\n", - " out.append_stdout('{} {} {}\\n'.format(i, '**'*i, something))\n", - " out.append_display_data(HTML(\"

All done!

\"))\n", - "\n", - "display('Display in main thread')\n", - "out = widgets.Output()\n", - "# Now the key: the container is displayed (while empty) in the main thread\n", - "display(out)\n", - "\n", - "thread = threading.Thread(\n", - " target=thread_func,\n", - " args=(\"some text\", out))\n", - "thread.start()" - ] - }, { "cell_type": "markdown", "metadata": { diff --git a/docs/source/examples/Widget Events.ipynb b/docs/source/examples/Widget Events.ipynb index 1e06ce5410..28f59bafc8 100644 --- a/docs/source/examples/Widget Events.ipynb +++ b/docs/source/examples/Widget Events.ipynb @@ -6,7 +6,7 @@ "nbsphinx": "hidden" }, "source": [ - "[Index](Index.ipynb) - [Back](Widget List.ipynb) - [Next](Widget Styling.ipynb)" + "[Index](Index.ipynb) - [Back](Output Widget.ipynb) - [Next](Widget Styling.ipynb)" ] }, { @@ -664,7 +664,7 @@ "nbsphinx": "hidden" }, "source": [ - "[Index](Index.ipynb) - [Back](Widget List.ipynb) - [Next](Widget Styling.ipynb)" + "[Index](Index.ipynb) - [Back](Output Widget.ipynb) - [Next](Widget Styling.ipynb)" ] } ], diff --git a/docs/source/examples/Widget List.ipynb b/docs/source/examples/Widget List.ipynb index 8b716251a2..5221ce102a 100644 --- a/docs/source/examples/Widget List.ipynb +++ b/docs/source/examples/Widget List.ipynb @@ -6,7 +6,7 @@ "nbsphinx": "hidden" }, "source": [ - "[Index](Index.ipynb) - [Back](Widget Basics.ipynb) - [Next](Widget Events.ipynb)" + "[Index](Index.ipynb) - [Back](Widget Basics.ipynb) - [Next](Output Widget.ipynb)" ] }, { @@ -1711,83 +1711,7 @@ "source": [ "## Output\n", "\n", - "The `Output` widget can capture and display stdout, stderr and [rich output generated by IPython](http://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#module-IPython.display). After the widget is created, direct output to it using a context manager." - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "af846c1a29fc4bd8bb0604e4090914d5", - "version_major": 2, - "version_minor": 0 - }, - "text/html": [ - "

Failed to display Jupyter Widget of type Output.

\n", - "

\n", - " If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean\n", - " that the widgets JavaScript is still loading. If this message persists, it\n", - " likely means that the widgets JavaScript library is either not installed or\n", - " not enabled. See the Jupyter\n", - " Widgets Documentation for setup instructions.\n", - "

\n", - "

\n", - " If you're reading this message in another frontend (for example, a static\n", - " rendering on GitHub or NBViewer),\n", - " it may mean that your frontend doesn't currently support widgets.\n", - "

\n" - ], - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "out = widgets.Output()\n", - "out" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can print text to the output area as shown below." - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [], - "source": [ - "with out:\n", - " for i in range(10):\n", - " print(i, 'Hello world!')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Rich material can also be directed to the output area. Anything which displays nicely in a Jupyter notebook will also display well in the `Output` widget." - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [], - "source": [ - "from IPython.display import YouTubeVideo\n", - "with out:\n", - " display(YouTubeVideo('eWzY2nGfkXk'))" + "The `Output` widget can capture and display stdout, stderr and [rich output generated by IPython](http://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#module-IPython.display). For detailed documentation, see the [output widget examples](/examples/Output Widget.html)." ] }, { @@ -2357,7 +2281,7 @@ "nbsphinx": "hidden" }, "source": [ - "[Index](Index.ipynb) - [Back](Widget Basics.ipynb) - [Next](Widget Events.ipynb)" + "[Index](Index.ipynb) - [Back](Widget Basics.ipynb) - [Next](Output Widget.ipynb)" ] } ], diff --git a/docs/source/user_guide.rst b/docs/source/user_guide.rst index 4d2c713610..4597a7ae6e 100644 --- a/docs/source/user_guide.rst +++ b/docs/source/user_guide.rst @@ -8,6 +8,7 @@ User Guide examples/Using Interact.ipynb examples/Widget Basics.ipynb examples/Widget List.ipynb + examples/Output Widget.ipynb examples/Widget Events.ipynb examples/Widget Styling.ipynb examples/Widget Custom.ipynb