Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/tqdm/std.py: 17%
696 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-30 06:35 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-30 06:35 +0000
1"""
2Customisable progressbar decorator for iterators.
3Includes a default `range` iterator printing to `stderr`.
5Usage:
6>>> from tqdm import trange, tqdm
7>>> for i in trange(10):
8... ...
9"""
10import sys
11from collections import OrderedDict, defaultdict
12from contextlib import contextmanager
13from datetime import datetime, timedelta
14from numbers import Number
15from time import time
16from warnings import warn
17from weakref import WeakSet
19from ._monitor import TMonitor
20from .utils import (
21 CallbackIOWrapper, Comparable, DisableOnWriteError, FormatReplace, SimpleTextIOWrapper,
22 _is_ascii, _screen_shape_wrapper, _supports_unicode, _term_move_up, disp_len, disp_trim,
23 envwrap)
25__author__ = "https://github.com/tqdm/tqdm#contributions"
26__all__ = ['tqdm', 'trange',
27 'TqdmTypeError', 'TqdmKeyError', 'TqdmWarning',
28 'TqdmExperimentalWarning', 'TqdmDeprecationWarning',
29 'TqdmMonitorWarning']
32class TqdmTypeError(TypeError):
33 pass
36class TqdmKeyError(KeyError):
37 pass
40class TqdmWarning(Warning):
41 """base class for all tqdm warnings.
43 Used for non-external-code-breaking errors, such as garbled printing.
44 """
45 def __init__(self, msg, fp_write=None, *a, **k):
46 if fp_write is not None:
47 fp_write("\n" + self.__class__.__name__ + ": " + str(msg).rstrip() + '\n')
48 else:
49 super(TqdmWarning, self).__init__(msg, *a, **k)
52class TqdmExperimentalWarning(TqdmWarning, FutureWarning):
53 """beta feature, unstable API and behaviour"""
54 pass
57class TqdmDeprecationWarning(TqdmWarning, DeprecationWarning):
58 # not suppressed if raised
59 pass
62class TqdmMonitorWarning(TqdmWarning, RuntimeWarning):
63 """tqdm monitor errors which do not affect external functionality"""
64 pass
67def TRLock(*args, **kwargs):
68 """threading RLock"""
69 try:
70 from threading import RLock
71 return RLock(*args, **kwargs)
72 except (ImportError, OSError): # pragma: no cover
73 pass
76class TqdmDefaultWriteLock(object):
77 """
78 Provide a default write lock for thread and multiprocessing safety.
79 Works only on platforms supporting `fork` (so Windows is excluded).
80 You must initialise a `tqdm` or `TqdmDefaultWriteLock` instance
81 before forking in order for the write lock to work.
82 On Windows, you need to supply the lock from the parent to the children as
83 an argument to joblib or the parallelism lib you use.
84 """
85 # global thread lock so no setup required for multithreading.
86 # NB: Do not create multiprocessing lock as it sets the multiprocessing
87 # context, disallowing `spawn()`/`forkserver()`
88 th_lock = TRLock()
90 def __init__(self):
91 # Create global parallelism locks to avoid racing issues with parallel
92 # bars works only if fork available (Linux/MacOSX, but not Windows)
93 cls = type(self)
94 root_lock = cls.th_lock
95 if root_lock is not None:
96 root_lock.acquire()
97 cls.create_mp_lock()
98 self.locks = [lk for lk in [cls.mp_lock, cls.th_lock] if lk is not None]
99 if root_lock is not None:
100 root_lock.release()
102 def acquire(self, *a, **k):
103 for lock in self.locks:
104 lock.acquire(*a, **k)
106 def release(self):
107 for lock in self.locks[::-1]: # Release in inverse order of acquisition
108 lock.release()
110 def __enter__(self):
111 self.acquire()
113 def __exit__(self, *exc):
114 self.release()
116 @classmethod
117 def create_mp_lock(cls):
118 if not hasattr(cls, 'mp_lock'):
119 try:
120 from multiprocessing import RLock
121 cls.mp_lock = RLock()
122 except (ImportError, OSError): # pragma: no cover
123 cls.mp_lock = None
125 @classmethod
126 def create_th_lock(cls):
127 assert hasattr(cls, 'th_lock')
128 warn("create_th_lock not needed anymore", TqdmDeprecationWarning, stacklevel=2)
131class Bar(object):
132 """
133 `str.format`-able bar with format specifiers: `[width][type]`
135 - `width`
136 + unspecified (default): use `self.default_len`
137 + `int >= 0`: overrides `self.default_len`
138 + `int < 0`: subtract from `self.default_len`
139 - `type`
140 + `a`: ascii (`charset=self.ASCII` override)
141 + `u`: unicode (`charset=self.UTF` override)
142 + `b`: blank (`charset=" "` override)
143 """
144 ASCII = " 123456789#"
145 UTF = u" " + u''.join(map(chr, range(0x258F, 0x2587, -1)))
146 BLANK = " "
147 COLOUR_RESET = '\x1b[0m'
148 COLOUR_RGB = '\x1b[38;2;%d;%d;%dm'
149 COLOURS = {'BLACK': '\x1b[30m', 'RED': '\x1b[31m', 'GREEN': '\x1b[32m',
150 'YELLOW': '\x1b[33m', 'BLUE': '\x1b[34m', 'MAGENTA': '\x1b[35m',
151 'CYAN': '\x1b[36m', 'WHITE': '\x1b[37m'}
153 def __init__(self, frac, default_len=10, charset=UTF, colour=None):
154 if not 0 <= frac <= 1:
155 warn("clamping frac to range [0, 1]", TqdmWarning, stacklevel=2)
156 frac = max(0, min(1, frac))
157 assert default_len > 0
158 self.frac = frac
159 self.default_len = default_len
160 self.charset = charset
161 self.colour = colour
163 @property
164 def colour(self):
165 return self._colour
167 @colour.setter
168 def colour(self, value):
169 if not value:
170 self._colour = None
171 return
172 try:
173 if value.upper() in self.COLOURS:
174 self._colour = self.COLOURS[value.upper()]
175 elif value[0] == '#' and len(value) == 7:
176 self._colour = self.COLOUR_RGB % tuple(
177 int(i, 16) for i in (value[1:3], value[3:5], value[5:7]))
178 else:
179 raise KeyError
180 except (KeyError, AttributeError):
181 warn("Unknown colour (%s); valid choices: [hex (#00ff00), %s]" % (
182 value, ", ".join(self.COLOURS)),
183 TqdmWarning, stacklevel=2)
184 self._colour = None
186 def __format__(self, format_spec):
187 if format_spec:
188 _type = format_spec[-1].lower()
189 try:
190 charset = {'a': self.ASCII, 'u': self.UTF, 'b': self.BLANK}[_type]
191 except KeyError:
192 charset = self.charset
193 else:
194 format_spec = format_spec[:-1]
195 if format_spec:
196 N_BARS = int(format_spec)
197 if N_BARS < 0:
198 N_BARS += self.default_len
199 else:
200 N_BARS = self.default_len
201 else:
202 charset = self.charset
203 N_BARS = self.default_len
205 nsyms = len(charset) - 1
206 bar_length, frac_bar_length = divmod(int(self.frac * N_BARS * nsyms), nsyms)
208 res = charset[-1] * bar_length
209 if bar_length < N_BARS: # whitespace padding
210 res = res + charset[frac_bar_length] + charset[0] * (N_BARS - bar_length - 1)
211 return self.colour + res + self.COLOUR_RESET if self.colour else res
214class EMA(object):
215 """
216 Exponential moving average: smoothing to give progressively lower
217 weights to older values.
219 Parameters
220 ----------
221 smoothing : float, optional
222 Smoothing factor in range [0, 1], [default: 0.3].
223 Increase to give more weight to recent values.
224 Ranges from 0 (yields old value) to 1 (yields new value).
225 """
226 def __init__(self, smoothing=0.3):
227 self.alpha = smoothing
228 self.last = 0
229 self.calls = 0
231 def __call__(self, x=None):
232 """
233 Parameters
234 ----------
235 x : float
236 New value to include in EMA.
237 """
238 beta = 1 - self.alpha
239 if x is not None:
240 self.last = self.alpha * x + beta * self.last
241 self.calls += 1
242 return self.last / (1 - beta ** self.calls) if self.calls else self.last
245class tqdm(Comparable):
246 """
247 Decorate an iterable object, returning an iterator which acts exactly
248 like the original iterable, but prints a dynamically updating
249 progressbar every time a value is requested.
251 Parameters
252 ----------
253 iterable : iterable, optional
254 Iterable to decorate with a progressbar.
255 Leave blank to manually manage the updates.
256 desc : str, optional
257 Prefix for the progressbar.
258 total : int or float, optional
259 The number of expected iterations. If unspecified,
260 len(iterable) is used if possible. If float("inf") or as a last
261 resort, only basic progress statistics are displayed
262 (no ETA, no progressbar).
263 If `gui` is True and this parameter needs subsequent updating,
264 specify an initial arbitrary large positive number,
265 e.g. 9e9.
266 leave : bool, optional
267 If [default: True], keeps all traces of the progressbar
268 upon termination of iteration.
269 If `None`, will leave only if `position` is `0`.
270 file : `io.TextIOWrapper` or `io.StringIO`, optional
271 Specifies where to output the progress messages
272 (default: sys.stderr). Uses `file.write(str)` and `file.flush()`
273 methods. For encoding, see `write_bytes`.
274 ncols : int, optional
275 The width of the entire output message. If specified,
276 dynamically resizes the progressbar to stay within this bound.
277 If unspecified, attempts to use environment width. The
278 fallback is a meter width of 10 and no limit for the counter and
279 statistics. If 0, will not print any meter (only stats).
280 mininterval : float, optional
281 Minimum progress display update interval [default: 0.1] seconds.
282 maxinterval : float, optional
283 Maximum progress display update interval [default: 10] seconds.
284 Automatically adjusts `miniters` to correspond to `mininterval`
285 after long display update lag. Only works if `dynamic_miniters`
286 or monitor thread is enabled.
287 miniters : int or float, optional
288 Minimum progress display update interval, in iterations.
289 If 0 and `dynamic_miniters`, will automatically adjust to equal
290 `mininterval` (more CPU efficient, good for tight loops).
291 If > 0, will skip display of specified number of iterations.
292 Tweak this and `mininterval` to get very efficient loops.
293 If your progress is erratic with both fast and slow iterations
294 (network, skipping items, etc) you should set miniters=1.
295 ascii : bool or str, optional
296 If unspecified or False, use unicode (smooth blocks) to fill
297 the meter. The fallback is to use ASCII characters " 123456789#".
298 disable : bool, optional
299 Whether to disable the entire progressbar wrapper
300 [default: False]. If set to None, disable on non-TTY.
301 unit : str, optional
302 String that will be used to define the unit of each iteration
303 [default: it].
304 unit_scale : bool or int or float, optional
305 If 1 or True, the number of iterations will be reduced/scaled
306 automatically and a metric prefix following the
307 International System of Units standard will be added
308 (kilo, mega, etc.) [default: False]. If any other non-zero
309 number, will scale `total` and `n`.
310 dynamic_ncols : bool, optional
311 If set, constantly alters `ncols` and `nrows` to the
312 environment (allowing for window resizes) [default: False].
313 smoothing : float, optional
314 Exponential moving average smoothing factor for speed estimates
315 (ignored in GUI mode). Ranges from 0 (average speed) to 1
316 (current/instantaneous speed) [default: 0.3].
317 bar_format : str, optional
318 Specify a custom bar string formatting. May impact performance.
319 [default: '{l_bar}{bar}{r_bar}'], where
320 l_bar='{desc}: {percentage:3.0f}%|' and
321 r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, '
322 '{rate_fmt}{postfix}]'
323 Possible vars: l_bar, bar, r_bar, n, n_fmt, total, total_fmt,
324 percentage, elapsed, elapsed_s, ncols, nrows, desc, unit,
325 rate, rate_fmt, rate_noinv, rate_noinv_fmt,
326 rate_inv, rate_inv_fmt, postfix, unit_divisor,
327 remaining, remaining_s, eta.
328 Note that a trailing ": " is automatically removed after {desc}
329 if the latter is empty.
330 initial : int or float, optional
331 The initial counter value. Useful when restarting a progress
332 bar [default: 0]. If using float, consider specifying `{n:.3f}`
333 or similar in `bar_format`, or specifying `unit_scale`.
334 position : int, optional
335 Specify the line offset to print this bar (starting from 0)
336 Automatic if unspecified.
337 Useful to manage multiple bars at once (eg, from threads).
338 postfix : dict or *, optional
339 Specify additional stats to display at the end of the bar.
340 Calls `set_postfix(**postfix)` if possible (dict).
341 unit_divisor : float, optional
342 [default: 1000], ignored unless `unit_scale` is True.
343 write_bytes : bool, optional
344 Whether to write bytes. If (default: False) will write unicode.
345 lock_args : tuple, optional
346 Passed to `refresh` for intermediate output
347 (initialisation, iterating, and updating).
348 nrows : int, optional
349 The screen height. If specified, hides nested bars outside this
350 bound. If unspecified, attempts to use environment height.
351 The fallback is 20.
352 colour : str, optional
353 Bar colour (e.g. 'green', '#00ff00').
354 delay : float, optional
355 Don't display until [default: 0] seconds have elapsed.
356 gui : bool, optional
357 WARNING: internal parameter - do not use.
358 Use tqdm.gui.tqdm(...) instead. If set, will attempt to use
359 matplotlib animations for a graphical output [default: False].
361 Returns
362 -------
363 out : decorated iterator.
364 """
366 monitor_interval = 10 # set to 0 to disable the thread
367 monitor = None
368 _instances = WeakSet()
370 @staticmethod
371 def format_sizeof(num, suffix='', divisor=1000):
372 """
373 Formats a number (greater than unity) with SI Order of Magnitude
374 prefixes.
376 Parameters
377 ----------
378 num : float
379 Number ( >= 1) to format.
380 suffix : str, optional
381 Post-postfix [default: ''].
382 divisor : float, optional
383 Divisor between prefixes [default: 1000].
385 Returns
386 -------
387 out : str
388 Number with Order of Magnitude SI unit postfix.
389 """
390 for unit in ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z']:
391 if abs(num) < 999.5:
392 if abs(num) < 99.95:
393 if abs(num) < 9.995:
394 return '{0:1.2f}'.format(num) + unit + suffix
395 return '{0:2.1f}'.format(num) + unit + suffix
396 return '{0:3.0f}'.format(num) + unit + suffix
397 num /= divisor
398 return '{0:3.1f}Y'.format(num) + suffix
400 @staticmethod
401 def format_interval(t):
402 """
403 Formats a number of seconds as a clock time, [H:]MM:SS
405 Parameters
406 ----------
407 t : int
408 Number of seconds.
410 Returns
411 -------
412 out : str
413 [H:]MM:SS
414 """
415 mins, s = divmod(int(t), 60)
416 h, m = divmod(mins, 60)
417 if h:
418 return '{0:d}:{1:02d}:{2:02d}'.format(h, m, s)
419 else:
420 return '{0:02d}:{1:02d}'.format(m, s)
422 @staticmethod
423 def format_num(n):
424 """
425 Intelligent scientific notation (.3g).
427 Parameters
428 ----------
429 n : int or float or Numeric
430 A Number.
432 Returns
433 -------
434 out : str
435 Formatted number.
436 """
437 f = '{0:.3g}'.format(n).replace('+0', '+').replace('-0', '-')
438 n = str(n)
439 return f if len(f) < len(n) else n
441 @staticmethod
442 def status_printer(file):
443 """
444 Manage the printing and in-place updating of a line of characters.
445 Note that if the string is longer than a line, then in-place
446 updating may not work (it will print a new line at each refresh).
447 """
448 fp = file
449 fp_flush = getattr(fp, 'flush', lambda: None) # pragma: no cover
450 if fp in (sys.stderr, sys.stdout):
451 getattr(sys.stderr, 'flush', lambda: None)()
452 getattr(sys.stdout, 'flush', lambda: None)()
454 def fp_write(s):
455 fp.write(str(s))
456 fp_flush()
458 last_len = [0]
460 def print_status(s):
461 len_s = disp_len(s)
462 fp_write('\r' + s + (' ' * max(last_len[0] - len_s, 0)))
463 last_len[0] = len_s
465 return print_status
467 @staticmethod
468 def format_meter(n, total, elapsed, ncols=None, prefix='', ascii=False, unit='it',
469 unit_scale=False, rate=None, bar_format=None, postfix=None,
470 unit_divisor=1000, initial=0, colour=None, **extra_kwargs):
471 """
472 Return a string-based progress bar given some parameters
474 Parameters
475 ----------
476 n : int or float
477 Number of finished iterations.
478 total : int or float
479 The expected total number of iterations. If meaningless (None),
480 only basic progress statistics are displayed (no ETA).
481 elapsed : float
482 Number of seconds passed since start.
483 ncols : int, optional
484 The width of the entire output message. If specified,
485 dynamically resizes `{bar}` to stay within this bound
486 [default: None]. If `0`, will not print any bar (only stats).
487 The fallback is `{bar:10}`.
488 prefix : str, optional
489 Prefix message (included in total width) [default: ''].
490 Use as {desc} in bar_format string.
491 ascii : bool, optional or str, optional
492 If not set, use unicode (smooth blocks) to fill the meter
493 [default: False]. The fallback is to use ASCII characters
494 " 123456789#".
495 unit : str, optional
496 The iteration unit [default: 'it'].
497 unit_scale : bool or int or float, optional
498 If 1 or True, the number of iterations will be printed with an
499 appropriate SI metric prefix (k = 10^3, M = 10^6, etc.)
500 [default: False]. If any other non-zero number, will scale
501 `total` and `n`.
502 rate : float, optional
503 Manual override for iteration rate.
504 If [default: None], uses n/elapsed.
505 bar_format : str, optional
506 Specify a custom bar string formatting. May impact performance.
507 [default: '{l_bar}{bar}{r_bar}'], where
508 l_bar='{desc}: {percentage:3.0f}%|' and
509 r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, '
510 '{rate_fmt}{postfix}]'
511 Possible vars: l_bar, bar, r_bar, n, n_fmt, total, total_fmt,
512 percentage, elapsed, elapsed_s, ncols, nrows, desc, unit,
513 rate, rate_fmt, rate_noinv, rate_noinv_fmt,
514 rate_inv, rate_inv_fmt, postfix, unit_divisor,
515 remaining, remaining_s, eta.
516 Note that a trailing ": " is automatically removed after {desc}
517 if the latter is empty.
518 postfix : *, optional
519 Similar to `prefix`, but placed at the end
520 (e.g. for additional stats).
521 Note: postfix is usually a string (not a dict) for this method,
522 and will if possible be set to postfix = ', ' + postfix.
523 However other types are supported (#382).
524 unit_divisor : float, optional
525 [default: 1000], ignored unless `unit_scale` is True.
526 initial : int or float, optional
527 The initial counter value [default: 0].
528 colour : str, optional
529 Bar colour (e.g. 'green', '#00ff00').
531 Returns
532 -------
533 out : Formatted meter and stats, ready to display.
534 """
536 # sanity check: total
537 if total and n >= (total + 0.5): # allow float imprecision (#849)
538 total = None
540 # apply custom scale if necessary
541 if unit_scale and unit_scale not in (True, 1):
542 if total:
543 total *= unit_scale
544 n *= unit_scale
545 if rate:
546 rate *= unit_scale # by default rate = self.avg_dn / self.avg_dt
547 unit_scale = False
549 elapsed_str = tqdm.format_interval(elapsed)
551 # if unspecified, attempt to use rate = average speed
552 # (we allow manual override since predicting time is an arcane art)
553 if rate is None and elapsed:
554 rate = (n - initial) / elapsed
555 inv_rate = 1 / rate if rate else None
556 format_sizeof = tqdm.format_sizeof
557 rate_noinv_fmt = ((format_sizeof(rate) if unit_scale else
558 '{0:5.2f}'.format(rate)) if rate else '?') + unit + '/s'
559 rate_inv_fmt = (
560 (format_sizeof(inv_rate) if unit_scale else '{0:5.2f}'.format(inv_rate))
561 if inv_rate else '?') + 's/' + unit
562 rate_fmt = rate_inv_fmt if inv_rate and inv_rate > 1 else rate_noinv_fmt
564 if unit_scale:
565 n_fmt = format_sizeof(n, divisor=unit_divisor)
566 total_fmt = format_sizeof(total, divisor=unit_divisor) if total is not None else '?'
567 else:
568 n_fmt = str(n)
569 total_fmt = str(total) if total is not None else '?'
571 try:
572 postfix = ', ' + postfix if postfix else ''
573 except TypeError:
574 pass
576 remaining = (total - n) / rate if rate and total else 0
577 remaining_str = tqdm.format_interval(remaining) if rate else '?'
578 try:
579 eta_dt = (datetime.now() + timedelta(seconds=remaining)
580 if rate and total else datetime.utcfromtimestamp(0))
581 except OverflowError:
582 eta_dt = datetime.max
584 # format the stats displayed to the left and right sides of the bar
585 if prefix:
586 # old prefix setup work around
587 bool_prefix_colon_already = (prefix[-2:] == ": ")
588 l_bar = prefix if bool_prefix_colon_already else prefix + ": "
589 else:
590 l_bar = ''
592 r_bar = f'| {n_fmt}/{total_fmt} [{elapsed_str}<{remaining_str}, {rate_fmt}{postfix}]'
594 # Custom bar formatting
595 # Populate a dict with all available progress indicators
596 format_dict = {
597 # slight extension of self.format_dict
598 'n': n, 'n_fmt': n_fmt, 'total': total, 'total_fmt': total_fmt,
599 'elapsed': elapsed_str, 'elapsed_s': elapsed,
600 'ncols': ncols, 'desc': prefix or '', 'unit': unit,
601 'rate': inv_rate if inv_rate and inv_rate > 1 else rate,
602 'rate_fmt': rate_fmt, 'rate_noinv': rate,
603 'rate_noinv_fmt': rate_noinv_fmt, 'rate_inv': inv_rate,
604 'rate_inv_fmt': rate_inv_fmt,
605 'postfix': postfix, 'unit_divisor': unit_divisor,
606 'colour': colour,
607 # plus more useful definitions
608 'remaining': remaining_str, 'remaining_s': remaining,
609 'l_bar': l_bar, 'r_bar': r_bar, 'eta': eta_dt,
610 **extra_kwargs}
612 # total is known: we can predict some stats
613 if total:
614 # fractional and percentage progress
615 frac = n / total
616 percentage = frac * 100
618 l_bar += '{0:3.0f}%|'.format(percentage)
620 if ncols == 0:
621 return l_bar[:-1] + r_bar[1:]
623 format_dict.update(l_bar=l_bar)
624 if bar_format:
625 format_dict.update(percentage=percentage)
627 # auto-remove colon for empty `{desc}`
628 if not prefix:
629 bar_format = bar_format.replace("{desc}: ", '')
630 else:
631 bar_format = "{l_bar}{bar}{r_bar}"
633 full_bar = FormatReplace()
634 nobar = bar_format.format(bar=full_bar, **format_dict)
635 if not full_bar.format_called:
636 return nobar # no `{bar}`; nothing else to do
638 # Formatting progress bar space available for bar's display
639 full_bar = Bar(frac,
640 max(1, ncols - disp_len(nobar)) if ncols else 10,
641 charset=Bar.ASCII if ascii is True else ascii or Bar.UTF,
642 colour=colour)
643 if not _is_ascii(full_bar.charset) and _is_ascii(bar_format):
644 bar_format = str(bar_format)
645 res = bar_format.format(bar=full_bar, **format_dict)
646 return disp_trim(res, ncols) if ncols else res
648 elif bar_format:
649 # user-specified bar_format but no total
650 l_bar += '|'
651 format_dict.update(l_bar=l_bar, percentage=0)
652 full_bar = FormatReplace()
653 nobar = bar_format.format(bar=full_bar, **format_dict)
654 if not full_bar.format_called:
655 return nobar
656 full_bar = Bar(0,
657 max(1, ncols - disp_len(nobar)) if ncols else 10,
658 charset=Bar.BLANK, colour=colour)
659 res = bar_format.format(bar=full_bar, **format_dict)
660 return disp_trim(res, ncols) if ncols else res
661 else:
662 # no total: no progressbar, ETA, just progress stats
663 return (f'{(prefix + ": ") if prefix else ""}'
664 f'{n_fmt}{unit} [{elapsed_str}, {rate_fmt}{postfix}]')
666 def __new__(cls, *_, **__):
667 instance = object.__new__(cls)
668 with cls.get_lock(): # also constructs lock if non-existent
669 cls._instances.add(instance)
670 # create monitoring thread
671 if cls.monitor_interval and (cls.monitor is None
672 or not cls.monitor.report()):
673 try:
674 cls.monitor = TMonitor(cls, cls.monitor_interval)
675 except Exception as e: # pragma: nocover
676 warn("tqdm:disabling monitor support"
677 " (monitor_interval = 0) due to:\n" + str(e),
678 TqdmMonitorWarning, stacklevel=2)
679 cls.monitor_interval = 0
680 return instance
682 @classmethod
683 def _get_free_pos(cls, instance=None):
684 """Skips specified instance."""
685 positions = {abs(inst.pos) for inst in cls._instances
686 if inst is not instance and hasattr(inst, "pos")}
687 return min(set(range(len(positions) + 1)).difference(positions))
689 @classmethod
690 def _decr_instances(cls, instance):
691 """
692 Remove from list and reposition another unfixed bar
693 to fill the new gap.
695 This means that by default (where all nested bars are unfixed),
696 order is not maintained but screen flicker/blank space is minimised.
697 (tqdm<=4.44.1 moved ALL subsequent unfixed bars up.)
698 """
699 with cls._lock:
700 try:
701 cls._instances.remove(instance)
702 except KeyError:
703 # if not instance.gui: # pragma: no cover
704 # raise
705 pass # py2: maybe magically removed already
706 # else:
707 if not instance.gui:
708 last = (instance.nrows or 20) - 1
709 # find unfixed (`pos >= 0`) overflow (`pos >= nrows - 1`)
710 instances = list(filter(
711 lambda i: hasattr(i, "pos") and last <= i.pos,
712 cls._instances))
713 # set first found to current `pos`
714 if instances:
715 inst = min(instances, key=lambda i: i.pos)
716 inst.clear(nolock=True)
717 inst.pos = abs(instance.pos)
719 @classmethod
720 def write(cls, s, file=None, end="\n", nolock=False):
721 """Print a message via tqdm (without overlap with bars)."""
722 fp = file if file is not None else sys.stdout
723 with cls.external_write_mode(file=file, nolock=nolock):
724 # Write the message
725 fp.write(s)
726 fp.write(end)
728 @classmethod
729 @contextmanager
730 def external_write_mode(cls, file=None, nolock=False):
731 """
732 Disable tqdm within context and refresh tqdm when exits.
733 Useful when writing to standard output stream
734 """
735 fp = file if file is not None else sys.stdout
737 try:
738 if not nolock:
739 cls.get_lock().acquire()
740 # Clear all bars
741 inst_cleared = []
742 for inst in getattr(cls, '_instances', []):
743 # Clear instance if in the target output file
744 # or if write output + tqdm output are both either
745 # sys.stdout or sys.stderr (because both are mixed in terminal)
746 if hasattr(inst, "start_t") and (inst.fp == fp or all(
747 f in (sys.stdout, sys.stderr) for f in (fp, inst.fp))):
748 inst.clear(nolock=True)
749 inst_cleared.append(inst)
750 yield
751 # Force refresh display of bars we cleared
752 for inst in inst_cleared:
753 inst.refresh(nolock=True)
754 finally:
755 if not nolock:
756 cls._lock.release()
758 @classmethod
759 def set_lock(cls, lock):
760 """Set the global lock."""
761 cls._lock = lock
763 @classmethod
764 def get_lock(cls):
765 """Get the global lock. Construct it if it does not exist."""
766 if not hasattr(cls, '_lock'):
767 cls._lock = TqdmDefaultWriteLock()
768 return cls._lock
770 @classmethod
771 def pandas(cls, **tqdm_kwargs):
772 """
773 Registers the current `tqdm` class with
774 pandas.core.
775 ( frame.DataFrame
776 | series.Series
777 | groupby.(generic.)DataFrameGroupBy
778 | groupby.(generic.)SeriesGroupBy
779 ).progress_apply
781 A new instance will be created every time `progress_apply` is called,
782 and each instance will automatically `close()` upon completion.
784 Parameters
785 ----------
786 tqdm_kwargs : arguments for the tqdm instance
788 Examples
789 --------
790 >>> import pandas as pd
791 >>> import numpy as np
792 >>> from tqdm import tqdm
793 >>> from tqdm.gui import tqdm as tqdm_gui
794 >>>
795 >>> df = pd.DataFrame(np.random.randint(0, 100, (100000, 6)))
796 >>> tqdm.pandas(ncols=50) # can use tqdm_gui, optional kwargs, etc
797 >>> # Now you can use `progress_apply` instead of `apply`
798 >>> df.groupby(0).progress_apply(lambda x: x**2)
800 References
801 ----------
802 <https://stackoverflow.com/questions/18603270/\
803 progress-indicator-during-pandas-operations-python>
804 """
805 from warnings import catch_warnings, simplefilter
807 from pandas.core.frame import DataFrame
808 from pandas.core.series import Series
809 try:
810 with catch_warnings():
811 simplefilter("ignore", category=FutureWarning)
812 from pandas import Panel
813 except ImportError: # pandas>=1.2.0
814 Panel = None
815 Rolling, Expanding = None, None
816 try: # pandas>=1.0.0
817 from pandas.core.window.rolling import _Rolling_and_Expanding
818 except ImportError:
819 try: # pandas>=0.18.0
820 from pandas.core.window import _Rolling_and_Expanding
821 except ImportError: # pandas>=1.2.0
822 try: # pandas>=1.2.0
823 from pandas.core.window.expanding import Expanding
824 from pandas.core.window.rolling import Rolling
825 _Rolling_and_Expanding = Rolling, Expanding
826 except ImportError: # pragma: no cover
827 _Rolling_and_Expanding = None
828 try: # pandas>=0.25.0
829 from pandas.core.groupby.generic import SeriesGroupBy # , NDFrameGroupBy
830 from pandas.core.groupby.generic import DataFrameGroupBy
831 except ImportError: # pragma: no cover
832 try: # pandas>=0.23.0
833 from pandas.core.groupby.groupby import DataFrameGroupBy, SeriesGroupBy
834 except ImportError:
835 from pandas.core.groupby import DataFrameGroupBy, SeriesGroupBy
836 try: # pandas>=0.23.0
837 from pandas.core.groupby.groupby import GroupBy
838 except ImportError: # pragma: no cover
839 from pandas.core.groupby import GroupBy
841 try: # pandas>=0.23.0
842 from pandas.core.groupby.groupby import PanelGroupBy
843 except ImportError:
844 try:
845 from pandas.core.groupby import PanelGroupBy
846 except ImportError: # pandas>=0.25.0
847 PanelGroupBy = None
849 tqdm_kwargs = tqdm_kwargs.copy()
850 deprecated_t = [tqdm_kwargs.pop('deprecated_t', None)]
852 def inner_generator(df_function='apply'):
853 def inner(df, func, *args, **kwargs):
854 """
855 Parameters
856 ----------
857 df : (DataFrame|Series)[GroupBy]
858 Data (may be grouped).
859 func : function
860 To be applied on the (grouped) data.
861 **kwargs : optional
862 Transmitted to `df.apply()`.
863 """
865 # Precompute total iterations
866 total = tqdm_kwargs.pop("total", getattr(df, 'ngroups', None))
867 if total is None: # not grouped
868 if df_function == 'applymap':
869 total = df.size
870 elif isinstance(df, Series):
871 total = len(df)
872 elif (_Rolling_and_Expanding is None or
873 not isinstance(df, _Rolling_and_Expanding)):
874 # DataFrame or Panel
875 axis = kwargs.get('axis', 0)
876 if axis == 'index':
877 axis = 0
878 elif axis == 'columns':
879 axis = 1
880 # when axis=0, total is shape[axis1]
881 total = df.size // df.shape[axis]
883 # Init bar
884 if deprecated_t[0] is not None:
885 t = deprecated_t[0]
886 deprecated_t[0] = None
887 else:
888 t = cls(total=total, **tqdm_kwargs)
890 if len(args) > 0:
891 # *args intentionally not supported (see #244, #299)
892 TqdmDeprecationWarning(
893 "Except func, normal arguments are intentionally" +
894 " not supported by" +
895 " `(DataFrame|Series|GroupBy).progress_apply`." +
896 " Use keyword arguments instead.",
897 fp_write=getattr(t.fp, 'write', sys.stderr.write))
899 try: # pandas>=1.3.0
900 from pandas.core.common import is_builtin_func
901 except ImportError:
902 is_builtin_func = df._is_builtin_func
903 try:
904 func = is_builtin_func(func)
905 except TypeError:
906 pass
908 # Define bar updating wrapper
909 def wrapper(*args, **kwargs):
910 # update tbar correctly
911 # it seems `pandas apply` calls `func` twice
912 # on the first column/row to decide whether it can
913 # take a fast or slow code path; so stop when t.total==t.n
914 t.update(n=1 if not t.total or t.n < t.total else 0)
915 return func(*args, **kwargs)
917 # Apply the provided function (in **kwargs)
918 # on the df using our wrapper (which provides bar updating)
919 try:
920 return getattr(df, df_function)(wrapper, **kwargs)
921 finally:
922 t.close()
924 return inner
926 # Monkeypatch pandas to provide easy methods
927 # Enable custom tqdm progress in pandas!
928 Series.progress_apply = inner_generator()
929 SeriesGroupBy.progress_apply = inner_generator()
930 Series.progress_map = inner_generator('map')
931 SeriesGroupBy.progress_map = inner_generator('map')
933 DataFrame.progress_apply = inner_generator()
934 DataFrameGroupBy.progress_apply = inner_generator()
935 DataFrame.progress_applymap = inner_generator('applymap')
937 if Panel is not None:
938 Panel.progress_apply = inner_generator()
939 if PanelGroupBy is not None:
940 PanelGroupBy.progress_apply = inner_generator()
942 GroupBy.progress_apply = inner_generator()
943 GroupBy.progress_aggregate = inner_generator('aggregate')
944 GroupBy.progress_transform = inner_generator('transform')
946 if Rolling is not None and Expanding is not None:
947 Rolling.progress_apply = inner_generator()
948 Expanding.progress_apply = inner_generator()
949 elif _Rolling_and_Expanding is not None:
950 _Rolling_and_Expanding.progress_apply = inner_generator()
952 # override defaults via env vars
953 @envwrap("TQDM_", is_method=True, types={'total': float, 'ncols': int, 'miniters': float,
954 'position': int, 'nrows': int})
955 def __init__(self, iterable=None, desc=None, total=None, leave=True, file=None,
956 ncols=None, mininterval=0.1, maxinterval=10.0, miniters=None,
957 ascii=None, disable=False, unit='it', unit_scale=False,
958 dynamic_ncols=False, smoothing=0.3, bar_format=None, initial=0,
959 position=None, postfix=None, unit_divisor=1000, write_bytes=False,
960 lock_args=None, nrows=None, colour=None, delay=0.0, gui=False,
961 **kwargs):
962 """see tqdm.tqdm for arguments"""
963 if file is None:
964 file = sys.stderr
966 if write_bytes:
967 # Despite coercing unicode into bytes, py2 sys.std* streams
968 # should have bytes written to them.
969 file = SimpleTextIOWrapper(
970 file, encoding=getattr(file, 'encoding', None) or 'utf-8')
972 file = DisableOnWriteError(file, tqdm_instance=self)
974 if disable is None and hasattr(file, "isatty") and not file.isatty():
975 disable = True
977 if total is None and iterable is not None:
978 try:
979 total = len(iterable)
980 except (TypeError, AttributeError):
981 total = None
982 if total == float("inf"):
983 # Infinite iterations, behave same as unknown
984 total = None
986 if disable:
987 self.iterable = iterable
988 self.disable = disable
989 with self._lock:
990 self.pos = self._get_free_pos(self)
991 self._instances.remove(self)
992 self.n = initial
993 self.total = total
994 self.leave = leave
995 return
997 if kwargs:
998 self.disable = True
999 with self._lock:
1000 self.pos = self._get_free_pos(self)
1001 self._instances.remove(self)
1002 raise (
1003 TqdmDeprecationWarning(
1004 "`nested` is deprecated and automated.\n"
1005 "Use `position` instead for manual control.\n",
1006 fp_write=getattr(file, 'write', sys.stderr.write))
1007 if "nested" in kwargs else
1008 TqdmKeyError("Unknown argument(s): " + str(kwargs)))
1010 # Preprocess the arguments
1011 if (
1012 (ncols is None or nrows is None) and (file in (sys.stderr, sys.stdout))
1013 ) or dynamic_ncols: # pragma: no cover
1014 if dynamic_ncols:
1015 dynamic_ncols = _screen_shape_wrapper()
1016 if dynamic_ncols:
1017 ncols, nrows = dynamic_ncols(file)
1018 else:
1019 _dynamic_ncols = _screen_shape_wrapper()
1020 if _dynamic_ncols:
1021 _ncols, _nrows = _dynamic_ncols(file)
1022 if ncols is None:
1023 ncols = _ncols
1024 if nrows is None:
1025 nrows = _nrows
1027 if miniters is None:
1028 miniters = 0
1029 dynamic_miniters = True
1030 else:
1031 dynamic_miniters = False
1033 if mininterval is None:
1034 mininterval = 0
1036 if maxinterval is None:
1037 maxinterval = 0
1039 if ascii is None:
1040 ascii = not _supports_unicode(file)
1042 if bar_format and ascii is not True and not _is_ascii(ascii):
1043 # Convert bar format into unicode since terminal uses unicode
1044 bar_format = str(bar_format)
1046 if smoothing is None:
1047 smoothing = 0
1049 # Store the arguments
1050 self.iterable = iterable
1051 self.desc = desc or ''
1052 self.total = total
1053 self.leave = leave
1054 self.fp = file
1055 self.ncols = ncols
1056 self.nrows = nrows
1057 self.mininterval = mininterval
1058 self.maxinterval = maxinterval
1059 self.miniters = miniters
1060 self.dynamic_miniters = dynamic_miniters
1061 self.ascii = ascii
1062 self.disable = disable
1063 self.unit = unit
1064 self.unit_scale = unit_scale
1065 self.unit_divisor = unit_divisor
1066 self.initial = initial
1067 self.lock_args = lock_args
1068 self.delay = delay
1069 self.gui = gui
1070 self.dynamic_ncols = dynamic_ncols
1071 self.smoothing = smoothing
1072 self._ema_dn = EMA(smoothing)
1073 self._ema_dt = EMA(smoothing)
1074 self._ema_miniters = EMA(smoothing)
1075 self.bar_format = bar_format
1076 self.postfix = None
1077 self.colour = colour
1078 self._time = time
1079 if postfix:
1080 try:
1081 self.set_postfix(refresh=False, **postfix)
1082 except TypeError:
1083 self.postfix = postfix
1085 # Init the iterations counters
1086 self.last_print_n = initial
1087 self.n = initial
1089 # if nested, at initial sp() call we replace '\r' by '\n' to
1090 # not overwrite the outer progress bar
1091 with self._lock:
1092 # mark fixed positions as negative
1093 self.pos = self._get_free_pos(self) if position is None else -position
1095 if not gui:
1096 # Initialize the screen printer
1097 self.sp = self.status_printer(self.fp)
1098 if delay <= 0:
1099 self.refresh(lock_args=self.lock_args)
1101 # Init the time counter
1102 self.last_print_t = self._time()
1103 # NB: Avoid race conditions by setting start_t at the very end of init
1104 self.start_t = self.last_print_t
1106 def __bool__(self):
1107 if self.total is not None:
1108 return self.total > 0
1109 if self.iterable is None:
1110 raise TypeError('bool() undefined when iterable == total == None')
1111 return bool(self.iterable)
1113 def __len__(self):
1114 return (
1115 self.total if self.iterable is None
1116 else self.iterable.shape[0] if hasattr(self.iterable, "shape")
1117 else len(self.iterable) if hasattr(self.iterable, "__len__")
1118 else self.iterable.__length_hint__() if hasattr(self.iterable, "__length_hint__")
1119 else getattr(self, "total", None))
1121 def __reversed__(self):
1122 try:
1123 orig = self.iterable
1124 except AttributeError:
1125 raise TypeError("'tqdm' object is not reversible")
1126 else:
1127 self.iterable = reversed(self.iterable)
1128 return self.__iter__()
1129 finally:
1130 self.iterable = orig
1132 def __contains__(self, item):
1133 contains = getattr(self.iterable, '__contains__', None)
1134 return contains(item) if contains is not None else item in self.__iter__()
1136 def __enter__(self):
1137 return self
1139 def __exit__(self, exc_type, exc_value, traceback):
1140 try:
1141 self.close()
1142 except AttributeError:
1143 # maybe eager thread cleanup upon external error
1144 if (exc_type, exc_value, traceback) == (None, None, None):
1145 raise
1146 warn("AttributeError ignored", TqdmWarning, stacklevel=2)
1148 def __del__(self):
1149 self.close()
1151 def __str__(self):
1152 return self.format_meter(**self.format_dict)
1154 @property
1155 def _comparable(self):
1156 return abs(getattr(self, "pos", 1 << 31))
1158 def __hash__(self):
1159 return id(self)
1161 def __iter__(self):
1162 """Backward-compatibility to use: for x in tqdm(iterable)"""
1164 # Inlining instance variables as locals (speed optimisation)
1165 iterable = self.iterable
1167 # If the bar is disabled, then just walk the iterable
1168 # (note: keep this check outside the loop for performance)
1169 if self.disable:
1170 for obj in iterable:
1171 yield obj
1172 return
1174 mininterval = self.mininterval
1175 last_print_t = self.last_print_t
1176 last_print_n = self.last_print_n
1177 min_start_t = self.start_t + self.delay
1178 n = self.n
1179 time = self._time
1181 try:
1182 for obj in iterable:
1183 yield obj
1184 # Update and possibly print the progressbar.
1185 # Note: does not call self.update(1) for speed optimisation.
1186 n += 1
1188 if n - last_print_n >= self.miniters:
1189 cur_t = time()
1190 dt = cur_t - last_print_t
1191 if dt >= mininterval and cur_t >= min_start_t:
1192 self.update(n - last_print_n)
1193 last_print_n = self.last_print_n
1194 last_print_t = self.last_print_t
1195 finally:
1196 self.n = n
1197 self.close()
1199 def update(self, n=1):
1200 """
1201 Manually update the progress bar, useful for streams
1202 such as reading files.
1203 E.g.:
1204 >>> t = tqdm(total=filesize) # Initialise
1205 >>> for current_buffer in stream:
1206 ... ...
1207 ... t.update(len(current_buffer))
1208 >>> t.close()
1209 The last line is highly recommended, but possibly not necessary if
1210 `t.update()` will be called in such a way that `filesize` will be
1211 exactly reached and printed.
1213 Parameters
1214 ----------
1215 n : int or float, optional
1216 Increment to add to the internal counter of iterations
1217 [default: 1]. If using float, consider specifying `{n:.3f}`
1218 or similar in `bar_format`, or specifying `unit_scale`.
1220 Returns
1221 -------
1222 out : bool or None
1223 True if a `display()` was triggered.
1224 """
1225 if self.disable:
1226 return
1228 if n < 0:
1229 self.last_print_n += n # for auto-refresh logic to work
1230 self.n += n
1232 # check counter first to reduce calls to time()
1233 if self.n - self.last_print_n >= self.miniters:
1234 cur_t = self._time()
1235 dt = cur_t - self.last_print_t
1236 if dt >= self.mininterval and cur_t >= self.start_t + self.delay:
1237 cur_t = self._time()
1238 dn = self.n - self.last_print_n # >= n
1239 if self.smoothing and dt and dn:
1240 # EMA (not just overall average)
1241 self._ema_dn(dn)
1242 self._ema_dt(dt)
1243 self.refresh(lock_args=self.lock_args)
1244 if self.dynamic_miniters:
1245 # If no `miniters` was specified, adjust automatically to the
1246 # maximum iteration rate seen so far between two prints.
1247 # e.g.: After running `tqdm.update(5)`, subsequent
1248 # calls to `tqdm.update()` will only cause an update after
1249 # at least 5 more iterations.
1250 if self.maxinterval and dt >= self.maxinterval:
1251 self.miniters = dn * (self.mininterval or self.maxinterval) / dt
1252 elif self.smoothing:
1253 # EMA miniters update
1254 self.miniters = self._ema_miniters(
1255 dn * (self.mininterval / dt if self.mininterval and dt
1256 else 1))
1257 else:
1258 # max iters between two prints
1259 self.miniters = max(self.miniters, dn)
1261 # Store old values for next call
1262 self.last_print_n = self.n
1263 self.last_print_t = cur_t
1264 return True
1266 def close(self):
1267 """Cleanup and (if leave=False) close the progressbar."""
1268 if self.disable:
1269 return
1271 # Prevent multiple closures
1272 self.disable = True
1274 # decrement instance pos and remove from internal set
1275 pos = abs(self.pos)
1276 self._decr_instances(self)
1278 if self.last_print_t < self.start_t + self.delay:
1279 # haven't ever displayed; nothing to clear
1280 return
1282 # GUI mode
1283 if getattr(self, 'sp', None) is None:
1284 return
1286 # annoyingly, _supports_unicode isn't good enough
1287 def fp_write(s):
1288 self.fp.write(str(s))
1290 try:
1291 fp_write('')
1292 except ValueError as e:
1293 if 'closed' in str(e):
1294 return
1295 raise # pragma: no cover
1297 leave = pos == 0 if self.leave is None else self.leave
1299 with self._lock:
1300 if leave:
1301 # stats for overall rate (no weighted average)
1302 self._ema_dt = lambda: None
1303 self.display(pos=0)
1304 fp_write('\n')
1305 else:
1306 # clear previous display
1307 if self.display(msg='', pos=pos) and not pos:
1308 fp_write('\r')
1310 def clear(self, nolock=False):
1311 """Clear current bar display."""
1312 if self.disable:
1313 return
1315 if not nolock:
1316 self._lock.acquire()
1317 pos = abs(self.pos)
1318 if pos < (self.nrows or 20):
1319 self.moveto(pos)
1320 self.sp('')
1321 self.fp.write('\r') # place cursor back at the beginning of line
1322 self.moveto(-pos)
1323 if not nolock:
1324 self._lock.release()
1326 def refresh(self, nolock=False, lock_args=None):
1327 """
1328 Force refresh the display of this bar.
1330 Parameters
1331 ----------
1332 nolock : bool, optional
1333 If `True`, does not lock.
1334 If [default: `False`]: calls `acquire()` on internal lock.
1335 lock_args : tuple, optional
1336 Passed to internal lock's `acquire()`.
1337 If specified, will only `display()` if `acquire()` returns `True`.
1338 """
1339 if self.disable:
1340 return
1342 if not nolock:
1343 if lock_args:
1344 if not self._lock.acquire(*lock_args):
1345 return False
1346 else:
1347 self._lock.acquire()
1348 self.display()
1349 if not nolock:
1350 self._lock.release()
1351 return True
1353 def unpause(self):
1354 """Restart tqdm timer from last print time."""
1355 if self.disable:
1356 return
1357 cur_t = self._time()
1358 self.start_t += cur_t - self.last_print_t
1359 self.last_print_t = cur_t
1361 def reset(self, total=None):
1362 """
1363 Resets to 0 iterations for repeated use.
1365 Consider combining with `leave=True`.
1367 Parameters
1368 ----------
1369 total : int or float, optional. Total to use for the new bar.
1370 """
1371 self.n = 0
1372 if total is not None:
1373 self.total = total
1374 if self.disable:
1375 return
1376 self.last_print_n = 0
1377 self.last_print_t = self.start_t = self._time()
1378 self._ema_dn = EMA(self.smoothing)
1379 self._ema_dt = EMA(self.smoothing)
1380 self._ema_miniters = EMA(self.smoothing)
1381 self.refresh()
1383 def set_description(self, desc=None, refresh=True):
1384 """
1385 Set/modify description of the progress bar.
1387 Parameters
1388 ----------
1389 desc : str, optional
1390 refresh : bool, optional
1391 Forces refresh [default: True].
1392 """
1393 self.desc = desc + ': ' if desc else ''
1394 if refresh:
1395 self.refresh()
1397 def set_description_str(self, desc=None, refresh=True):
1398 """Set/modify description without ': ' appended."""
1399 self.desc = desc or ''
1400 if refresh:
1401 self.refresh()
1403 def set_postfix(self, ordered_dict=None, refresh=True, **kwargs):
1404 """
1405 Set/modify postfix (additional stats)
1406 with automatic formatting based on datatype.
1408 Parameters
1409 ----------
1410 ordered_dict : dict or OrderedDict, optional
1411 refresh : bool, optional
1412 Forces refresh [default: True].
1413 kwargs : dict, optional
1414 """
1415 # Sort in alphabetical order to be more deterministic
1416 postfix = OrderedDict([] if ordered_dict is None else ordered_dict)
1417 for key in sorted(kwargs.keys()):
1418 postfix[key] = kwargs[key]
1419 # Preprocess stats according to datatype
1420 for key in postfix.keys():
1421 # Number: limit the length of the string
1422 if isinstance(postfix[key], Number):
1423 postfix[key] = self.format_num(postfix[key])
1424 # Else for any other type, try to get the string conversion
1425 elif not isinstance(postfix[key], str):
1426 postfix[key] = str(postfix[key])
1427 # Else if it's a string, don't need to preprocess anything
1428 # Stitch together to get the final postfix
1429 self.postfix = ', '.join(key + '=' + postfix[key].strip()
1430 for key in postfix.keys())
1431 if refresh:
1432 self.refresh()
1434 def set_postfix_str(self, s='', refresh=True):
1435 """
1436 Postfix without dictionary expansion, similar to prefix handling.
1437 """
1438 self.postfix = str(s)
1439 if refresh:
1440 self.refresh()
1442 def moveto(self, n):
1443 # TODO: private method
1444 self.fp.write('\n' * n + _term_move_up() * -n)
1445 getattr(self.fp, 'flush', lambda: None)()
1447 @property
1448 def format_dict(self):
1449 """Public API for read-only member access."""
1450 if self.disable and not hasattr(self, 'unit'):
1451 return defaultdict(lambda: None, {
1452 'n': self.n, 'total': self.total, 'elapsed': 0, 'unit': 'it'})
1453 if self.dynamic_ncols:
1454 self.ncols, self.nrows = self.dynamic_ncols(self.fp)
1455 return {
1456 'n': self.n, 'total': self.total,
1457 'elapsed': self._time() - self.start_t if hasattr(self, 'start_t') else 0,
1458 'ncols': self.ncols, 'nrows': self.nrows, 'prefix': self.desc,
1459 'ascii': self.ascii, 'unit': self.unit, 'unit_scale': self.unit_scale,
1460 'rate': self._ema_dn() / self._ema_dt() if self._ema_dt() else None,
1461 'bar_format': self.bar_format, 'postfix': self.postfix,
1462 'unit_divisor': self.unit_divisor, 'initial': self.initial,
1463 'colour': self.colour}
1465 def display(self, msg=None, pos=None):
1466 """
1467 Use `self.sp` to display `msg` in the specified `pos`.
1469 Consider overloading this function when inheriting to use e.g.:
1470 `self.some_frontend(**self.format_dict)` instead of `self.sp`.
1472 Parameters
1473 ----------
1474 msg : str, optional. What to display (default: `repr(self)`).
1475 pos : int, optional. Position to `moveto`
1476 (default: `abs(self.pos)`).
1477 """
1478 if pos is None:
1479 pos = abs(self.pos)
1481 nrows = self.nrows or 20
1482 if pos >= nrows - 1:
1483 if pos >= nrows:
1484 return False
1485 if msg or msg is None: # override at `nrows - 1`
1486 msg = " ... (more hidden) ..."
1488 if not hasattr(self, "sp"):
1489 raise TqdmDeprecationWarning(
1490 "Please use `tqdm.gui.tqdm(...)`"
1491 " instead of `tqdm(..., gui=True)`\n",
1492 fp_write=getattr(self.fp, 'write', sys.stderr.write))
1494 if pos:
1495 self.moveto(pos)
1496 self.sp(self.__str__() if msg is None else msg)
1497 if pos:
1498 self.moveto(-pos)
1499 return True
1501 @classmethod
1502 @contextmanager
1503 def wrapattr(cls, stream, method, total=None, bytes=True, **tqdm_kwargs):
1504 """
1505 stream : file-like object.
1506 method : str, "read" or "write". The result of `read()` and
1507 the first argument of `write()` should have a `len()`.
1509 >>> with tqdm.wrapattr(file_obj, "read", total=file_obj.size) as fobj:
1510 ... while True:
1511 ... chunk = fobj.read(chunk_size)
1512 ... if not chunk:
1513 ... break
1514 """
1515 with cls(total=total, **tqdm_kwargs) as t:
1516 if bytes:
1517 t.unit = "B"
1518 t.unit_scale = True
1519 t.unit_divisor = 1024
1520 yield CallbackIOWrapper(t.update, stream, method)
1523def trange(*args, **kwargs):
1524 """Shortcut for tqdm(range(*args), **kwargs)."""
1525 return tqdm(range(*args), **kwargs)