tqdm
(read taqadum, تقدّم) means "progress" in arabic.
Instantly make your loops show a progress meter - just wrap any iterable with "tqdm(iterable)", and you're done!
from tqdm import tqdm
for i in tqdm(range(9)):
...
Here's what the output looks like:
76%|████████████████████ | 7641/10000 [00:34<00:10, 222.22 it/s]
trange(N)
can be also used as a convenient shortcut for
tqdm(xrange(N))
.
Overhead is low -- about 60ns per iteration (80ns with gui=True
).
By comparison, the well established
ProgressBar has
an 800ns/iter overhead. It's a matter of taste, but we also like to think our
version is much more visually appealing.
tqdm
works on any platform (Linux/Windows/Mac), in any console or in a
GUI, and is also friendly with IPython/Jupyter notebooks.
pip install tqdm
Pull and install in the current directory:
pip install -e git+https://github.com/tqdm/tqdm.git@master#egg=tqdm
class tqdm(object):
"""
Decorate an iterable object, returning an iterator which acts exactly
like the orignal iterable, but prints a dynamically updating
progressbar every time a value is requested.
"""
def __init__(self, iterable=None, desc=None, total=None, leave=False,
file=sys.stderr, ncols=None, mininterval=0.1,
maxinterval=10.0, miniters=None, ascii=None, disable=False,
unit='it', unit_scale=False, dynamic_ncols=False,
smoothing=0.3, gui=False):
- iterable : iterable, optional
Iterable to decorate with a progressbar. Leave blank [default: None] to manually manage the updates.
- desc : str, optional
Prefix for the progressbar [default: None].
- total : int, optional
The number of expected iterations. If not given, len(iterable) is used if possible. As a last resort, only basic progress statistics are displayed (no ETA, no progressbar). If gui is True and this parameter needs subsequent updating, specify an initial arbitrary large positive integer, e.g. int(9e9).
- leave : bool, optional
If [default: False], removes all traces of the progressbar upon termination of iteration.
- file : io.TextIOWrapper or io.StringIO, optional
Specifies where to output the progress messages [default: sys.stderr]. Uses file.write(str) and file.flush() methods.
- ncols : int, optional
The width of the entire output message. If specified, dynamically resizes the progressbar to stay within this bound. If [default: None], attempts to use environment width. The fallback is a meter width of 10 and no limit for the counter and statistics. If 0, will not print any meter (only stats).
- mininterval : float, optional
Minimum progress update interval, in seconds [default: 0.1].
- maxinterval : float, optional
Maximum progress update interval, in seconds [default: 10.0].
- miniters : int, optional
Minimum progress update interval, in iterations [default: None]. If specified, will set mininterval to 0.
- ascii : bool, optional
If [default: None] or false, use unicode (smooth blocks) to fill the meter. The fallback is to use ASCII characters 1-9 #.
- disable : bool
Whether to disable the entire progressbar wrapper [default: False].
- unit : str, optional
String that will be used to define the unit of each iteration [default: 'it'].
- unit_scale : bool, optional
If set, the number of iterations will be reduced/scaled automatically and a metric prefix following the International System of Units standard will be added (kilo, mega, etc.) [default: False].
- dynamic_ncols : bool, optional
If set, constantly alters ncols to the environment (allowing for window resizes) [default: False].
- smoothing : float
Exponential moving average smoothing factor for speed estimates (ignored in GUI mode). Ranges from 0 (average speed) to 1 (current/instantaneous speed) [default: 0.3].
- out : decorated iterator.
def update(self, n=1):
"""
Manually update the progress bar, useful for streams
such as reading files.
E.g.:
>>> t = tqdm(total=filesize) # Initialise
>>> for current_buffer in stream:
... ...
... t.update(len(current_buffer))
>>> t.close()
The last line is highly recommended, but possibly not necessary if
`t.update()` will be called in such a way that `filesize` will be
exactly reached and printed.
Parameters
----------
n : int
Increment to add to the internal counter of iterations
[default: 1].
"""
def close(self):
"""
Cleanup and (if leave=False) close the progressbar.
"""
def trange(*args, **kwargs):
"""
A shortcut for tqdm(xrange(*args), **kwargs).
On Python3+ range is used instead of xrange.
"""
class tqdm_gui(tqdm):
"""
Experimental GUI version of tqdm!
"""
def tgrange(*args, **kwargs):
"""
Experimental GUI version of trange!
"""
See the examples folder or
import the module and run help()
.
tqdm
can easily support callbacks/hooks and manual updates.
Here's an example with urllib
:
urllib.urlretrieve documentation
[...]If present, the hook function will be called onceon establishment of the network connection and once after each block readthereafter. The hook will be passed three arguments; a count of blockstransferred so far, a block size in bytes, and the total size of the file.[...]
import urllib
from tqdm import tqdm
def my_hook(t):
"""
Wraps tqdm instance. Don't forget to close() or __exit__()
the tqdm instance once you're done with it (easiest using `with` syntax).
Example
-------
>>> with tqdm(...) as t:
... reporthook = my_hook(t)
... urllib.urlretrieve(..., reporthook=reporthook)
"""
last_b = [0]
def inner(b=1, bsize=1, tsize=None):
"""
b : int, optional
Number of blocks just transferred [default: 1].
bsize : int, optional
Size of each block (in tqdm units) [default: 1].
tsize : int, optional
Total size (in tqdm units). If [default: None] remains unchanged.
"""
if tsize is not None:
t.total = tsize
t.update((b - last_b[0]) * bsize)
last_b[0] = b
return inner
eg_link = 'http://www.doc.ic.ac.uk/~cod11/matryoshka.zip'
with tqdm(unit='B', unit_scale=True, leave=True, miniters=1,
desc=eg_link.split('/')[-1]) as t: # all optional kwargs
urllib.urlretrieve(eg_link, filename='/dev/null',
reporthook=my_hook(t), data=None)
It is recommend to use miniters=1
whenever there is potentially
large differences in iteration speed (e.g. downloading a file over
a patchy connection).
Due to popular demand we've added support for pandas
-- here's an example
for DataFrameGroupBy.progress_apply
:
import pandas as pd
import numpy as np
from tqdm import tqdm, tqdm_pandas
df = pd.DataFrame(np.random.randint(0, 100, (100000, 6)))
# Create and register a new `tqdm` instance with `pandas`
# (can use tqdm_gui, optional kwargs, etc.)
tqdm_pandas(tqdm())
# Now you can use `progress_apply` instead of `apply`
df.groupby(0).progress_apply(lambda x: x**2)
In case you're interested in how this works (and how to modify it for your
own callbacks), see the examples
folder or import the module and run help()
.
To run the testing suite please make sure tox (http://tox.testrun.org/)
is installed, then type tox
from the command line.
Alternatively if you don't want to use tox
, a Makefile is provided
with the following commands:
$ make flake8
$ make test
$ make coverage
See the CONTRIBUTE file for more information.
- Casper da Costa-Luis (casperdcl)
- Stephen Larroque (lrq3000)
- Hadrien Mary (hadim)
- Noam Yorav-Raphael (noamraph)*
- Ivan Ivanov (obiwanus)
- Mikhail Korobov (kmike)
* Original author