Updating Displays.ipynb
359 lines
| 7.8 KiB
| text/plain
|
TextLexer
Min RK
|
r23014 | { | ||
"cells": [ | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"# Updatable Displays\n", | ||||
"\n", | ||||
"Note: This feature requires notebook >= 5.0 or JupyterLab, and \n", | ||||
"\n", | ||||
"\n", | ||||
"IPython 6 implements a new API as part of the Jupyter Protocol version 5.1 for easily updating displays.\n", | ||||
"\n", | ||||
"When you display something, you can now pass a `display_id` argument to attach an id to that output.\n", | ||||
"\n", | ||||
"Any future display with the same ID will also update other displays that had the same ID.\n", | ||||
"\n", | ||||
"`display` with a `display_id` will return a `DisplayHandle`\n", | ||||
"object, which gives you easy access to update the output:" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": 10, | ||||
"metadata": { | ||||
"collapsed": true | ||||
}, | ||||
"outputs": [], | ||||
"source": [ | ||||
"from IPython.display import display, update_display" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": 13, | ||||
"metadata": {}, | ||||
"outputs": [ | ||||
{ | ||||
"data": { | ||||
"text/plain": [ | ||||
"'z'" | ||||
] | ||||
}, | ||||
"metadata": {}, | ||||
"output_type": "display_data" | ||||
}, | ||||
{ | ||||
"data": { | ||||
"text/plain": [ | ||||
"<DisplayHandle display_id=update-me>" | ||||
] | ||||
}, | ||||
"execution_count": 13, | ||||
"metadata": {}, | ||||
"output_type": "execute_result" | ||||
} | ||||
], | ||||
"source": [ | ||||
"handle = display('x', display_id='update-me')\n", | ||||
"handle" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"When we call `handle.display('y')`, we get a new display of 'y',\n", | ||||
"but in addition to that, we updated the previous display." | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": 14, | ||||
"metadata": {}, | ||||
"outputs": [ | ||||
{ | ||||
"data": { | ||||
"text/plain": [ | ||||
"'z'" | ||||
] | ||||
}, | ||||
"metadata": {}, | ||||
"output_type": "display_data" | ||||
} | ||||
], | ||||
"source": [ | ||||
"handle.display('y')" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"We can also *just* update the existing displays,\n", | ||||
"without creating a new display:" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": 15, | ||||
"metadata": { | ||||
"collapsed": true | ||||
}, | ||||
"outputs": [], | ||||
"source": [ | ||||
"handle.update('z')" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"You don't have to generate display_ids yourself,\n", | ||||
"if you specify `display_id=True`, then a unique ID will be assigned:" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": 16, | ||||
"metadata": {}, | ||||
"outputs": [ | ||||
{ | ||||
"data": { | ||||
"text/plain": [ | ||||
"'hello'" | ||||
] | ||||
}, | ||||
"metadata": {}, | ||||
"output_type": "display_data" | ||||
}, | ||||
{ | ||||
"data": { | ||||
"text/plain": [ | ||||
"<DisplayHandle display_id=07fc47b2ef652ccb70addeee3eb0981a>" | ||||
] | ||||
}, | ||||
"execution_count": 16, | ||||
"metadata": {}, | ||||
"output_type": "execute_result" | ||||
} | ||||
], | ||||
"source": [ | ||||
"handle = display(\"hello\", display_id=True)\n", | ||||
"handle" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"Calling `handle.display(obj)` is the same as calling `display(obj, handle.display_id)`,\n", | ||||
"so you don't need to use the handle objects if you don't want to:" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": 17, | ||||
"metadata": {}, | ||||
"outputs": [ | ||||
{ | ||||
"data": { | ||||
"text/plain": [ | ||||
"'z'" | ||||
] | ||||
}, | ||||
"metadata": {}, | ||||
"output_type": "display_data" | ||||
} | ||||
], | ||||
"source": [ | ||||
"display('x', display_id='here');" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": 18, | ||||
"metadata": {}, | ||||
"outputs": [ | ||||
{ | ||||
"data": { | ||||
"text/plain": [ | ||||
"'z'" | ||||
] | ||||
}, | ||||
"metadata": {}, | ||||
"output_type": "display_data" | ||||
} | ||||
], | ||||
"source": [ | ||||
"display('y', display_id='here');" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"And just like `display`, there is now `update_display`,\n", | ||||
"which is what `DisplayHandle.update` calls:" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": 19, | ||||
"metadata": { | ||||
"collapsed": true | ||||
}, | ||||
"outputs": [], | ||||
"source": [ | ||||
"update_display('z', display_id='here')" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"## More detailed example\n", | ||||
"\n", | ||||
"One of the motivating use cases for this is simple progress bars.\n", | ||||
"\n", | ||||
"Here is an example ProgressBar using these APIs:" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": 35, | ||||
"metadata": {}, | ||||
"outputs": [ | ||||
{ | ||||
"data": { | ||||
"text/html": [ | ||||
"<progress\n", | ||||
" value=10\n", | ||||
" max=10\n", | ||||
" style=\"width: 60ex\"/>\n", | ||||
" 10 / 10\n", | ||||
" " | ||||
], | ||||
"text/plain": [ | ||||
"[============================================================] 10/10" | ||||
] | ||||
}, | ||||
"metadata": {}, | ||||
"output_type": "display_data" | ||||
} | ||||
], | ||||
"source": [ | ||||
"import os\n", | ||||
"from binascii import hexlify\n", | ||||
"\n", | ||||
"class ProgressBar(object):\n", | ||||
" def __init__(self, capacity):\n", | ||||
" self.progress = 0\n", | ||||
" self.capacity = capacity\n", | ||||
" self.html_width = '60ex'\n", | ||||
" self.text_width = 60\n", | ||||
" self._display_id = hexlify(os.urandom(8)).decode('ascii')\n", | ||||
" \n", | ||||
" def __repr__(self):\n", | ||||
" fraction = self.progress / self.capacity\n", | ||||
" filled = '=' * int(fraction * self.text_width)\n", | ||||
" rest = ' ' * (self.text_width - len(filled))\n", | ||||
" return '[{}{}] {}/{}'.format(\n", | ||||
" filled, rest,\n", | ||||
" self.progress, self.capacity,\n", | ||||
" )\n", | ||||
" \n", | ||||
" def _repr_html_(self):\n", | ||||
" return \"\"\"<progress\n", | ||||
" value={progress}\n", | ||||
" max={capacity}\n", | ||||
" style=\"width: {width}\"/>\n", | ||||
" {progress} / {capacity}\n", | ||||
" \"\"\".format(\n", | ||||
" progress=self.progress,\n", | ||||
" capacity=self.capacity,\n", | ||||
" width=self.html_width,\n", | ||||
" )\n", | ||||
" \n", | ||||
" def display(self):\n", | ||||
" display(self, display_id=self._display_id)\n", | ||||
" \n", | ||||
" def update(self):\n", | ||||
" update_display(self, display_id=self._display_id)\n", | ||||
"\n", | ||||
"bar = ProgressBar(10)\n", | ||||
"bar.display()" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"And the ProgressBar has `.display` and `.update` methods:" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": 36, | ||||
"metadata": {}, | ||||
"outputs": [ | ||||
{ | ||||
"data": { | ||||
"text/html": [ | ||||
"<progress\n", | ||||
" value=10\n", | ||||
" max=10\n", | ||||
" style=\"width: 60ex\"/>\n", | ||||
" 10 / 10\n", | ||||
" " | ||||
], | ||||
"text/plain": [ | ||||
"[============================================================] 10/10" | ||||
] | ||||
}, | ||||
"metadata": {}, | ||||
"output_type": "display_data" | ||||
} | ||||
], | ||||
"source": [ | ||||
"import time\n", | ||||
"\n", | ||||
"bar.display()\n", | ||||
"\n", | ||||
"for i in range(11):\n", | ||||
" bar.progress = i\n", | ||||
" bar.update()\n", | ||||
" time.sleep(0.25)" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"We would encourage any updatable-display objects that track their own display_ids to follow-suit with `.display()` and `.update()` or `.update_display()` methods." | ||||
] | ||||
} | ||||
], | ||||
"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.5.1" | ||||
} | ||||
}, | ||||
"nbformat": 4, | ||||
"nbformat_minor": 1 | ||||
} | ||||