Created
June 14, 2018 22:55
-
-
Save Joshua1989/7c7bce4e317b099ef507eea4d02657d6 to your computer and use it in GitHub Desktop.
Solution of unexpected spacing on nested tqdm progressbars by adding a VBox container
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "cells": [ | |
| { | |
| "metadata": {}, | |
| "cell_type": "markdown", | |
| "source": "Solution of unexpected spacing on nested tqdm progressbars by adding a VBox container" | |
| }, | |
| { | |
| "metadata": { | |
| "ExecuteTime": { | |
| "start_time": "2018-06-14T22:50:00.609881Z", | |
| "end_time": "2018-06-14T22:50:00.630930Z" | |
| }, | |
| "code_folding": [ | |
| 196, | |
| 206, | |
| 215, | |
| 229, | |
| 233 | |
| ], | |
| "trusted": true | |
| }, | |
| "cell_type": "code", | |
| "source": "\"\"\"\nIPython/Jupyter Notebook progressbar decorator for iterators.\nIncludes a default (x)range iterator printing to stderr.\nUsage:\n >>> from tqdm_notebook import tnrange[, tqdm_notebook]\n >>> for i in tnrange(10): #same as: for i in tqdm_notebook(xrange(10))\n ... ...\n\"\"\"\n# future division is important to divide integers and get as\n# a result precise floating numbers (instead of truncated int)\nfrom __future__ import division, absolute_import\n# import compatibility functions and utilities\nimport sys\nfrom tqdm._utils import _range\n# to inherit from the tqdm class\nfrom tqdm._tqdm import tqdm\n\nif True: # pragma: no cover\n # import IPython/Jupyter base widget and display utilities\n try: # IPython 4.x\n import ipywidgets\n IPY = 4\n except ImportError: # IPython 3.x / 2.x\n IPY = 32\n import warnings\n with warnings.catch_warnings():\n ipy_deprecation_msg = \"The `IPython.html` package\" \\\n \" has been deprecated\"\n warnings.filterwarnings('error',\n message=\".*\" + ipy_deprecation_msg + \".*\")\n try:\n import IPython.html.widgets as ipywidgets\n except Warning as e:\n if ipy_deprecation_msg not in str(e):\n raise\n warnings.simplefilter('ignore')\n try:\n import IPython.html.widgets as ipywidgets # NOQA\n except ImportError:\n pass\n except ImportError:\n pass\n\n try: # IPython 4.x / 3.x\n if IPY == 32:\n from IPython.html.widgets import IntProgress, HBox, HTML\n IPY = 3\n else:\n from ipywidgets import IntProgress, HBox, HTML\n except ImportError:\n try: # IPython 2.x\n from IPython.html.widgets import IntProgressWidget as IntProgress\n from IPython.html.widgets import ContainerWidget as HBox\n from IPython.html.widgets import HTML\n IPY = 2\n except ImportError:\n IPY = 0\n\n try:\n from IPython.display import display # , clear_output\n except ImportError:\n pass\n\n # HTML encoding\n try: # Py3\n from html import escape\n except ImportError: # Py2\n from cgi import escape\n\n__author__ = {\"github.com/\": [\"lrq3000\", \"casperdcl\", \"alexanderkuk\"]}\n__all__ = ['tqdm_notebook_EX', 'tnrange_EX']\n \nclass tqdm_notebook_EX(tqdm):\n \"\"\"\n Experimental IPython/Jupyter Notebook widget using tqdm!\n \"\"\"\n\n def status_printer(self, _, total=None, desc=None, ncols=None):\n \"\"\"\n Manage the printing of an IPython/Jupyter Notebook progress bar widget.\n \"\"\"\n # Fallback to text bar if there's no total\n # DEPRECATED: replaced with an 'info' style bar\n # if not total:\n # return super(tqdm_notebook_EX, tqdm_notebook).status_printer(file)\n\n # fp = file\n\n # Prepare IPython progress bar\n if total:\n pbar = IntProgress(min=0, max=total)\n else: # No total? Show info style bar with no progress tqdm status\n pbar = IntProgress(min=0, max=1)\n pbar.value = 1\n pbar.bar_style = 'info'\n if desc:\n pbar.description = desc\n # Prepare status text\n ptext = HTML()\n # Only way to place text to the right of the bar is to use a container\n container = HBox(children=[pbar, ptext])\n if self.vbox:\n self.vbox.children = self.vbox.children + (container,)\n else:\n display(container)\n # Prepare layout\n if ncols is not None: # use default style of ipywidgets\n # ncols could be 100, \"100px\", \"100%\"\n ncols = str(ncols) # ipywidgets only accepts string\n if ncols[-1].isnumeric():\n # if last value is digit, assume the value is digit\n ncols += 'px'\n pbar.layout.flex = '2'\n container.layout.width = ncols\n container.layout.display = 'inline-flex'\n container.layout.flex_flow = 'row wrap'\n\n def print_status(s='', close=False, bar_style=None, desc=None):\n # Note: contrary to native tqdm, s='' does NOT clear bar\n # goal is to keep all infos if error happens so user knows\n # at which iteration the loop failed.\n\n # Clear previous output (really necessary?)\n # clear_output(wait=1)\n\n # Get current iteration value from format_meter string\n if total:\n # n = None\n if s:\n npos = s.find(r'/|/') # cause we use bar_format=r'{n}|...'\n # Check that n can be found in s (else n > total)\n if npos >= 0:\n n = int(s[:npos]) # get n from string\n s = s[npos + 3:] # remove from string\n\n # Update bar with current n value\n if n is not None:\n pbar.value = n\n\n # Print stats\n if s: # never clear the bar (signal: s='')\n s = s.replace('||', '') # remove inesthetical pipes\n s = escape(s) # html escape special characters (like '?')\n ptext.value = s\n\n # Change bar style\n if bar_style:\n # Hack-ish way to avoid the danger bar_style being overriden by\n # success because the bar gets closed after the error...\n if not (pbar.bar_style == 'danger' and bar_style == 'success'):\n pbar.bar_style = bar_style\n\n # Special signal to close the bar\n if close and pbar.bar_style != 'danger': # hide only if no error\n try:\n container.close()\n except AttributeError:\n container.visible = False\n if self.vbox:\n self.vbox.children = tuple(ch for ch in self.vbox.children if ch is not container)\n\n # Update description\n if desc:\n pbar.description = desc\n\n return print_status\n\n def __init__(self, *args, **kwargs):\n # Setup default output\n if kwargs.get('file', sys.stderr) is sys.stderr:\n kwargs['file'] = sys.stdout # avoid the red block in IPython\n\n # Remove the bar from the printed string, only print stats\n if not kwargs.get('bar_format', None):\n kwargs['bar_format'] = r'{n}/|/{l_bar}{r_bar}'\n\n # Initialize parent class + avoid printing by using gui=True\n kwargs['gui'] = True\n # Set VBox as the overall container, useful for nested bars in Jupyter\n self.vbox = kwargs.pop('vbox', None)\n super(tqdm_notebook_EX, self).__init__(*args, **kwargs)\n if self.disable or not kwargs['gui']:\n return\n\n # Delete first pbar generated from super() (wrong total and text)\n # DEPRECATED by using gui=True\n # self.sp('', close=True)\n\n # Get bar width\n self.ncols = '100%' if self.dynamic_ncols else kwargs.get(\"ncols\", None)\n\n # Replace with IPython progress bar display (with correct total)\n self.sp = self.status_printer(\n self.fp, self.total, self.desc, self.ncols)\n self.desc = None # trick to place description before the bar\n\n # Print initial bar state\n if not self.disable:\n self.sp(self.__repr__()) # same as self.refresh without clearing\n\n def __iter__(self, *args, **kwargs):\n try:\n for obj in super(tqdm_notebook_EX, self).__iter__(*args, **kwargs):\n # return super(tqdm...) will not catch exception\n yield obj\n # NB: except ... [ as ...] breaks IPython async KeyboardInterrupt\n except: # NOQA\n self.sp(bar_style='danger')\n raise\n\n def update(self, *args, **kwargs):\n try:\n super(tqdm_notebook_EX, self).update(*args, **kwargs)\n except Exception as exc:\n # cannot catch KeyboardInterrupt when using manual tqdm\n # as the interrupt will most likely happen on another statement\n self.sp(bar_style='danger')\n raise exc\n\n def close(self, *args, **kwargs):\n super(tqdm_notebook_EX, self).close(*args, **kwargs)\n # If it was not run in a notebook, sp is not assigned, check for it\n if hasattr(self, 'sp'):\n # Try to detect if there was an error or KeyboardInterrupt\n # in manual mode: if n < total, things probably got wrong\n if self.total and self.n < self.total:\n self.sp(bar_style='danger')\n else:\n if self.leave:\n self.sp(bar_style='success')\n else:\n self.sp(close=True)\n\n def moveto(self, *args, **kwargs):\n # void -> avoid extraneous `\\n` in IPython output cell\n return\n\n def set_description(self, desc=None, **_):\n \"\"\"\n Set/modify description of the progress bar.\n Parameters\n ----------\n desc : str, optional\n \"\"\"\n self.sp(desc=desc)\n\n\ndef tnrange_EX(*args, **kwargs):\n \"\"\"\n A shortcut for tqdm_notebook(xrange(*args), **kwargs).\n On Python3+ range is used instead of xrange.\n \"\"\"\n return tqdm_notebook_EX(_range(*args), **kwargs)\n", | |
| "execution_count": 63, | |
| "outputs": [] | |
| }, | |
| { | |
| "metadata": {}, | |
| "cell_type": "markdown", | |
| "source": "Example code: before adding container" | |
| }, | |
| { | |
| "metadata": { | |
| "ExecuteTime": { | |
| "start_time": "2018-06-14T22:53:24.154431Z", | |
| "end_time": "2018-06-14T22:53:29.603895Z" | |
| }, | |
| "trusted": true | |
| }, | |
| "cell_type": "code", | |
| "source": "for i in tnrange_EX(10):\n print('i =', i)\n for j in tnrange_EX(5, leave=False):\n sleep(0.1)", | |
| "execution_count": 72, | |
| "outputs": [ | |
| { | |
| "output_type": "display_data", | |
| "data": { | |
| "text/plain": "HBox(children=(IntProgress(value=0, max=10), HTML(value='')))", | |
| "application/vnd.jupyter.widget-view+json": { | |
| "version_major": 2, | |
| "version_minor": 0, | |
| "model_id": "ecb6146c1aaa49fb8f29d8c0ca517a20" | |
| } | |
| }, | |
| "metadata": {} | |
| }, | |
| { | |
| "output_type": "stream", | |
| "text": "i = 0\n", | |
| "name": "stdout" | |
| }, | |
| { | |
| "output_type": "display_data", | |
| "data": { | |
| "text/plain": "HBox(children=(IntProgress(value=0, max=5), HTML(value='')))", | |
| "application/vnd.jupyter.widget-view+json": { | |
| "version_major": 2, | |
| "version_minor": 0, | |
| "model_id": "1705c3349ed54712bfa14896511d6e5b" | |
| } | |
| }, | |
| "metadata": {} | |
| }, | |
| { | |
| "output_type": "stream", | |
| "text": "i = 1\n", | |
| "name": "stdout" | |
| }, | |
| { | |
| "output_type": "display_data", | |
| "data": { | |
| "text/plain": "HBox(children=(IntProgress(value=0, max=5), HTML(value='')))", | |
| "application/vnd.jupyter.widget-view+json": { | |
| "version_major": 2, | |
| "version_minor": 0, | |
| "model_id": "c9566b9ab41f495fa918321cf8e138af" | |
| } | |
| }, | |
| "metadata": {} | |
| }, | |
| { | |
| "output_type": "stream", | |
| "text": "i = 2\n", | |
| "name": "stdout" | |
| }, | |
| { | |
| "output_type": "display_data", | |
| "data": { | |
| "text/plain": "HBox(children=(IntProgress(value=0, max=5), HTML(value='')))", | |
| "application/vnd.jupyter.widget-view+json": { | |
| "version_major": 2, | |
| "version_minor": 0, | |
| "model_id": "01ca8d06f9f24d89a15c48d96497bda8" | |
| } | |
| }, | |
| "metadata": {} | |
| }, | |
| { | |
| "output_type": "stream", | |
| "text": "i = 3\n", | |
| "name": "stdout" | |
| }, | |
| { | |
| "output_type": "display_data", | |
| "data": { | |
| "text/plain": "HBox(children=(IntProgress(value=0, max=5), HTML(value='')))", | |
| "application/vnd.jupyter.widget-view+json": { | |
| "version_major": 2, | |
| "version_minor": 0, | |
| "model_id": "44fa0d2bf8aa4a768b89aabe17a43d14" | |
| } | |
| }, | |
| "metadata": {} | |
| }, | |
| { | |
| "output_type": "stream", | |
| "text": "i = 4\n", | |
| "name": "stdout" | |
| }, | |
| { | |
| "output_type": "display_data", | |
| "data": { | |
| "text/plain": "HBox(children=(IntProgress(value=0, max=5), HTML(value='')))", | |
| "application/vnd.jupyter.widget-view+json": { | |
| "version_major": 2, | |
| "version_minor": 0, | |
| "model_id": "7b525852e7574dd8b2246736a5836989" | |
| } | |
| }, | |
| "metadata": {} | |
| }, | |
| { | |
| "output_type": "stream", | |
| "text": "i = 5\n", | |
| "name": "stdout" | |
| }, | |
| { | |
| "output_type": "display_data", | |
| "data": { | |
| "text/plain": "HBox(children=(IntProgress(value=0, max=5), HTML(value='')))", | |
| "application/vnd.jupyter.widget-view+json": { | |
| "version_major": 2, | |
| "version_minor": 0, | |
| "model_id": "0baf8149e748459d9b80e429a94b47be" | |
| } | |
| }, | |
| "metadata": {} | |
| }, | |
| { | |
| "output_type": "stream", | |
| "text": "i = 6\n", | |
| "name": "stdout" | |
| }, | |
| { | |
| "output_type": "display_data", | |
| "data": { | |
| "text/plain": "HBox(children=(IntProgress(value=0, max=5), HTML(value='')))", | |
| "application/vnd.jupyter.widget-view+json": { | |
| "version_major": 2, | |
| "version_minor": 0, | |
| "model_id": "50cc722f98f44cc1b32cc73c04353618" | |
| } | |
| }, | |
| "metadata": {} | |
| }, | |
| { | |
| "output_type": "stream", | |
| "text": "i = 7\n", | |
| "name": "stdout" | |
| }, | |
| { | |
| "output_type": "display_data", | |
| "data": { | |
| "text/plain": "HBox(children=(IntProgress(value=0, max=5), HTML(value='')))", | |
| "application/vnd.jupyter.widget-view+json": { | |
| "version_major": 2, | |
| "version_minor": 0, | |
| "model_id": "a30ca9114bd24762bc3e9e1e4403aa2c" | |
| } | |
| }, | |
| "metadata": {} | |
| }, | |
| { | |
| "output_type": "stream", | |
| "text": "i = 8\n", | |
| "name": "stdout" | |
| }, | |
| { | |
| "output_type": "display_data", | |
| "data": { | |
| "text/plain": "HBox(children=(IntProgress(value=0, max=5), HTML(value='')))", | |
| "application/vnd.jupyter.widget-view+json": { | |
| "version_major": 2, | |
| "version_minor": 0, | |
| "model_id": "65b177cacffa436b8f0bc184a17b5e4b" | |
| } | |
| }, | |
| "metadata": {} | |
| }, | |
| { | |
| "output_type": "stream", | |
| "text": "i = 9\n", | |
| "name": "stdout" | |
| }, | |
| { | |
| "output_type": "display_data", | |
| "data": { | |
| "text/plain": "HBox(children=(IntProgress(value=0, max=5), HTML(value='')))", | |
| "application/vnd.jupyter.widget-view+json": { | |
| "version_major": 2, | |
| "version_minor": 0, | |
| "model_id": "28ae85cecb9d4ce394343322c5797b77" | |
| } | |
| }, | |
| "metadata": {} | |
| }, | |
| { | |
| "output_type": "stream", | |
| "text": "\n", | |
| "name": "stdout" | |
| } | |
| ] | |
| }, | |
| { | |
| "metadata": {}, | |
| "cell_type": "markdown", | |
| "source": "Example code: after adding container" | |
| }, | |
| { | |
| "metadata": { | |
| "ExecuteTime": { | |
| "start_time": "2018-06-14T22:53:40.191683Z", | |
| "end_time": "2018-06-14T22:53:45.589001Z" | |
| }, | |
| "trusted": true | |
| }, | |
| "cell_type": "code", | |
| "source": "vb = VBox()\ndisplay(vb)\nfor i in tnrange_EX(10, vbox=vb):\n print('i =', i)\n for j in tnrange_EX(5, leave=False, vbox=vb):\n sleep(0.1)", | |
| "execution_count": 73, | |
| "outputs": [ | |
| { | |
| "output_type": "display_data", | |
| "data": { | |
| "text/plain": "VBox()", | |
| "application/vnd.jupyter.widget-view+json": { | |
| "version_major": 2, | |
| "version_minor": 0, | |
| "model_id": "46343c683d0342f69efcefc6e310ba14" | |
| } | |
| }, | |
| "metadata": {} | |
| }, | |
| { | |
| "output_type": "stream", | |
| "text": "i = 0\ni = 1\ni = 2\ni = 3\ni = 4\ni = 5\ni = 6\ni = 7\ni = 8\ni = 9\n\n", | |
| "name": "stdout" | |
| } | |
| ] | |
| } | |
| ], | |
| "metadata": { | |
| "hide_input": false, | |
| "kernelspec": { | |
| "name": "python3", | |
| "display_name": "Python 3", | |
| "language": "python" | |
| }, | |
| "varInspector": { | |
| "window_display": false, | |
| "cols": { | |
| "lenName": 16, | |
| "lenType": 16, | |
| "lenVar": 40 | |
| }, | |
| "kernels_config": { | |
| "python": { | |
| "library": "var_list.py", | |
| "delete_cmd_prefix": "del ", | |
| "delete_cmd_postfix": "", | |
| "varRefreshCmd": "print(var_dic_list())" | |
| }, | |
| "r": { | |
| "library": "var_list.r", | |
| "delete_cmd_prefix": "rm(", | |
| "delete_cmd_postfix": ") ", | |
| "varRefreshCmd": "cat(var_dic_list()) " | |
| } | |
| }, | |
| "types_to_exclude": [ | |
| "module", | |
| "function", | |
| "builtin_function_or_method", | |
| "instance", | |
| "_Feature" | |
| ] | |
| }, | |
| "gist": { | |
| "id": "020e4c60efeda4b28ddf7966ea22f45f", | |
| "data": { | |
| "description": "Solution of unexpected spacing on nested tqdm progressbars by adding a VBox container", | |
| "public": true | |
| } | |
| }, | |
| "_draft": { | |
| "nbviewer_url": "https://gist.github.com/020e4c60efeda4b28ddf7966ea22f45f" | |
| } | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 2 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment