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