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