2013-10-26 19:54:46 +00:00
|
|
|
__all__ = ['tqdm', 'trange']
|
|
|
|
|
|
|
|
import sys
|
|
|
|
import time
|
|
|
|
|
|
|
|
def format_interval(t):
|
|
|
|
mins, s = divmod(int(t), 60)
|
|
|
|
h, m = divmod(mins, 60)
|
|
|
|
if h:
|
|
|
|
return '%d:%02d:%02d' % (h, m, s)
|
|
|
|
else:
|
|
|
|
return '%02d:%02d' % (m, s)
|
|
|
|
|
|
|
|
def format_meter(n, total, elapsed):
|
|
|
|
# n - number of finished iterations
|
|
|
|
# total - total number of iterations, or None
|
|
|
|
# elapsed - number of seconds passed since start
|
|
|
|
if n > total:
|
|
|
|
total = None
|
|
|
|
|
|
|
|
elapsed_str = format_interval(elapsed)
|
|
|
|
rate = '%5.2f' % (n / elapsed) if elapsed else '?'
|
|
|
|
|
|
|
|
if total:
|
|
|
|
frac = float(n) / total
|
|
|
|
|
|
|
|
N_BARS = 10
|
|
|
|
bar_length = int(frac*N_BARS)
|
|
|
|
bar = '#'*bar_length + '-'*(N_BARS-bar_length)
|
|
|
|
|
|
|
|
percentage = '%3d%%' % (frac * 100)
|
|
|
|
|
|
|
|
left_str = format_interval(elapsed / n * (total-n)) if n else '?'
|
|
|
|
|
|
|
|
return '|%s| %d/%d %s [elapsed: %s left: %s, %s iters/sec]' % (
|
|
|
|
bar, n, total, percentage, elapsed_str, left_str, rate)
|
|
|
|
|
|
|
|
else:
|
|
|
|
return '%d [elapsed: %s, %s iters/sec]' % (n, elapsed_str, rate)
|
|
|
|
|
|
|
|
class StatusPrinter(object):
|
2014-01-10 20:33:17 +00:00
|
|
|
def __init__(self, output_to=sys.stdout):
|
|
|
|
self.output_to = output_to
|
2013-10-26 19:54:46 +00:00
|
|
|
self.last_printed_len = 0
|
|
|
|
|
|
|
|
def print_status(self, s):
|
2014-01-10 20:33:17 +00:00
|
|
|
self.output_to.write('\r'+s+' '*max(self.last_printed_len-len(s), 0))
|
|
|
|
self.output_to.flush()
|
2013-10-26 19:54:46 +00:00
|
|
|
self.last_printed_len = len(s)
|
|
|
|
|
2014-01-10 20:33:17 +00:00
|
|
|
def tqdm(iterable, desc='', total=None, leave=False, mininterval=0.5, miniters=1, output_to=sys.stdout):
|
2013-10-26 19:54:46 +00:00
|
|
|
"""
|
|
|
|
Get an iterable object, and return an iterator which acts exactly like the
|
|
|
|
iterable, but prints a progress meter and updates it every time a value is
|
|
|
|
requested.
|
|
|
|
'desc' can contain a short string, describing the progress, that is added
|
|
|
|
in the beginning of the line.
|
|
|
|
'total' can give the number of expected iterations. If not given,
|
|
|
|
len(iterable) is used if it is defined.
|
|
|
|
If leave is False, tqdm deletes its traces from screen after it has finished
|
|
|
|
iterating over all elements.
|
|
|
|
If less than mininterval seconds or miniters iterations have passed since
|
|
|
|
the last progress meter update, it is not updated again.
|
2014-01-10 20:54:35 +00:00
|
|
|
'output_to' can be a file-like object to output the progress message to
|
|
|
|
If not specified, prints to sys.stdout.
|
2013-10-26 19:54:46 +00:00
|
|
|
"""
|
|
|
|
if total is None:
|
|
|
|
try:
|
|
|
|
total = len(iterable)
|
|
|
|
except TypeError:
|
|
|
|
total = None
|
|
|
|
|
|
|
|
prefix = desc+': ' if desc else ''
|
|
|
|
|
2014-01-10 20:33:17 +00:00
|
|
|
sp = StatusPrinter(output_to)
|
2013-10-26 19:54:46 +00:00
|
|
|
sp.print_status(prefix + format_meter(0, total, 0))
|
|
|
|
|
|
|
|
start_t = last_print_t = time.time()
|
|
|
|
last_print_n = 0
|
|
|
|
n = 0
|
|
|
|
for obj in iterable:
|
|
|
|
yield obj
|
|
|
|
# Now the object was created and processed, so we can print the meter.
|
|
|
|
n += 1
|
|
|
|
if n - last_print_n >= miniters:
|
|
|
|
# We check the counter first, to reduce the overhead of time.time().
|
|
|
|
cur_t = time.time()
|
|
|
|
if cur_t - last_print_t >= mininterval:
|
|
|
|
sp.print_status(prefix + format_meter(n, total, cur_t-start_t))
|
|
|
|
last_print_n = n
|
|
|
|
last_print_t = cur_t
|
|
|
|
|
|
|
|
if not leave:
|
|
|
|
sp.print_status('')
|
|
|
|
sys.stdout.write('\r')
|
|
|
|
else:
|
|
|
|
if last_print_n < n:
|
|
|
|
cur_t = time.time()
|
|
|
|
sp.print_status(prefix + format_meter(n, total, cur_t-start_t))
|
|
|
|
|
|
|
|
def trange(*args, **kwargs):
|
2014-01-11 21:33:42 +00:00
|
|
|
"""A shortcut for writing tqdm(range()) on py3 or tqdm(xrange()) on py2"""
|
2014-01-11 16:43:20 +00:00
|
|
|
try:
|
|
|
|
f = xrange
|
|
|
|
except NameError:
|
|
|
|
f = range
|
|
|
|
|
|
|
|
return tqdm(f(*args), **kwargs)
|