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

703 statements  

1""" 

2Customisable progress bar decorator for iterators. 

3Includes a default `range` iterator printing to `stderr`. 

4 

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 

18 

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) 

24 

25__author__ = "https://github.com/tqdm/tqdm#contributions" 

26__all__ = ['tqdm', 'trange', 

27 'TqdmTypeError', 'TqdmKeyError', 'TqdmWarning', 

28 'TqdmExperimentalWarning', 'TqdmDeprecationWarning', 

29 'TqdmMonitorWarning'] 

30 

31 

32class TqdmTypeError(TypeError): 

33 pass 

34 

35 

36class TqdmKeyError(KeyError): 

37 pass 

38 

39 

40class TqdmWarning(Warning): 

41 """base class for all tqdm warnings. 

42 

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) 

50 

51 

52class TqdmExperimentalWarning(TqdmWarning, FutureWarning): 

53 """beta feature, unstable API and behaviour""" 

54 

55 

56class TqdmDeprecationWarning(TqdmWarning, DeprecationWarning): 

57 """may be removed in a future release""" 

58 # not suppressed if raised 

59 

60 

61class TqdmMonitorWarning(TqdmWarning, RuntimeWarning): 

62 """tqdm monitor errors which do not affect external functionality""" 

63 

64 

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 

72 

73 

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() 

87 

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() 

99 

100 def acquire(self, *a, **k): 

101 for lock in self.locks: 

102 lock.acquire(*a, **k) 

103 

104 def release(self): 

105 for lock in self.locks[::-1]: # Release in inverse order of acquisition 

106 lock.release() 

107 

108 def __enter__(self): 

109 self.acquire() 

110 

111 def __exit__(self, *exc): 

112 self.release() 

113 

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 

122 

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) 

127 

128 

129class Bar: 

130 """ 

131 `str.format`-able bar with format specifiers: `[width][type]` 

132 

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'} 

150 

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 

160 

161 @property 

162 def colour(self): 

163 return self._colour 

164 

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 

182 

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 

201 

202 nsyms = len(charset) - 1 

203 bar_length, frac_bar_length = divmod(int(self.frac * N_BARS * nsyms), nsyms) 

204 

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 

209 

210 

211class EMA: 

212 """ 

213 Exponential moving average: smoothing to give progressively lower 

214 weights to older values. 

215 

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 

227 

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 

240 

241 

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. 

247 

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]. 

357 

358 Returns 

359 ------- 

360 out : decorated iterator. 

361 """ 

362 

363 monitor_interval = 10 # set to 0 to disable the thread 

364 monitor = None 

365 _instances = WeakSet() 

366 

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. 

372 

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]. 

381 

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}' 

396 

397 @staticmethod 

398 def format_interval(t): 

399 """ 

400 Formats a number of seconds as a clock time, [H:]MM:SS 

401 

402 Parameters 

403 ---------- 

404 t : int 

405 Number of seconds. 

406 

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}' 

416 

417 @staticmethod 

418 def format_num(n): 

419 """ 

420 Intelligent scientific notation (.3g). 

421 

422 Parameters 

423 ---------- 

424 n : int or float or Numeric 

425 A Number. 

426 

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 

435 

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)() 

448 

449 def fp_write(s): 

450 fp.write(str(s)) 

451 fp_flush() 

452 

453 last_len = [0] 

454 

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 

459 

460 return print_status 

461 

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 

469 

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'). 

526 

527 Returns 

528 ------- 

529 out : Formatted meter and stats, ready to display. 

530 """ 

531 

532 # sanity check: total 

533 if total and (n >= (total + 0.5) or total == float("inf")): 

534 # allow float imprecision (#849) or inf (#651) 

535 total = None 

536 

537 # apply custom scale if necessary 

538 if unit_scale and unit_scale not in (True, 1): 

539 if total: 

540 total *= unit_scale 

541 n *= unit_scale 

542 if rate: 

543 rate *= unit_scale # by default rate = self.avg_dn / self.avg_dt 

544 unit_scale = False 

545 

546 elapsed_str = tqdm.format_interval(elapsed) 

547 

548 # if unspecified, attempt to use rate = average speed 

549 # (we allow manual override since predicting time is an arcane art) 

550 if rate is None and elapsed: 

551 rate = (n - initial) / elapsed 

552 inv_rate = 1 / rate if rate else None 

553 format_sizeof = tqdm.format_sizeof 

554 rate_noinv_fmt = ((format_sizeof(rate) if unit_scale else f'{rate:5.2f}') 

555 if rate else '?') + unit + '/s' 

556 rate_inv_fmt = ( 

557 (format_sizeof(inv_rate) if unit_scale else f'{inv_rate:5.2f}') 

558 if inv_rate else '?') + 's/' + unit 

559 rate_fmt = rate_inv_fmt if inv_rate and inv_rate > 1 else rate_noinv_fmt 

560 

561 if unit_scale: 

562 n_fmt = format_sizeof(n, divisor=unit_divisor) 

563 total_fmt = format_sizeof(total, divisor=unit_divisor) if total is not None else '?' 

564 else: 

565 n_fmt = str(n) 

566 total_fmt = str(total) if total is not None else '?' 

567 

568 try: 

569 postfix = ', ' + postfix if postfix else '' 

570 except TypeError: 

571 pass 

572 

573 remaining = (total - n) / rate if rate and total else 0 

574 remaining_str = tqdm.format_interval(remaining) if rate else '?' 

575 try: 

576 eta_dt = (datetime.now() + timedelta(seconds=remaining) 

577 if rate and total else datetime.fromtimestamp(0, timezone.utc)) 

578 except OverflowError: 

579 eta_dt = datetime.max 

580 

581 # format the stats displayed to the left and right sides of the bar 

582 if prefix: 

583 # old prefix setup work around 

584 bool_prefix_colon_already = (prefix[-2:] == ": ") 

585 l_bar = prefix if bool_prefix_colon_already else prefix + ": " 

586 else: 

587 l_bar = '' 

588 

589 r_bar = f'| {n_fmt}/{total_fmt} [{elapsed_str}<{remaining_str}, {rate_fmt}{postfix}]' 

590 

591 # Custom bar formatting 

592 # Populate a dict with all available progress indicators 

593 format_dict = { 

594 # slight extension of self.format_dict 

595 'n': n, 'n_fmt': n_fmt, 'total': total, 'total_fmt': total_fmt, 

596 'elapsed': elapsed_str, 'elapsed_s': elapsed, 

597 'ncols': ncols, 'desc': prefix or '', 'unit': unit, 

598 'rate': inv_rate if inv_rate and inv_rate > 1 else rate, 

599 'rate_fmt': rate_fmt, 'rate_noinv': rate, 

600 'rate_noinv_fmt': rate_noinv_fmt, 'rate_inv': inv_rate, 

601 'rate_inv_fmt': rate_inv_fmt, 

602 'postfix': postfix, 'unit_divisor': unit_divisor, 

603 'colour': colour, 

604 # plus more useful definitions 

605 'remaining': remaining_str, 'remaining_s': remaining, 

606 'l_bar': l_bar, 'r_bar': r_bar, 'eta': eta_dt, 

607 **extra_kwargs} 

608 

609 # total is known: we can predict some stats 

610 if total: 

611 # fractional and percentage progress 

612 frac = n / total 

613 percentage = frac * 100 

614 

615 l_bar += f'{percentage:3.0f}%|' 

616 

617 if ncols == 0: 

618 return l_bar[:-1] + r_bar[1:] 

619 

620 format_dict.update(l_bar=l_bar) 

621 if bar_format: 

622 format_dict.update(percentage=percentage) 

623 

624 # auto-remove colon for empty `{desc}` 

625 if not prefix: 

626 bar_format = bar_format.replace("{desc}: ", '') 

627 else: 

628 bar_format = "{l_bar}{bar}{r_bar}" 

629 

630 full_bar = FormatReplace() 

631 nobar = bar_format.format(bar=full_bar, **format_dict) # no `{bar}` 

632 if not full_bar.format_called: 

633 return disp_trim(nobar, ncols) if ncols else nobar 

634 

635 # Formatting progress bar space available for bar's display 

636 full_bar = Bar(frac, 

637 max(1, ncols - disp_len(nobar)) if ncols else 10, 

638 charset=Bar.ASCII if ascii is True else ascii or Bar.UTF, 

639 colour=colour) 

640 if not _is_ascii(full_bar.charset) and _is_ascii(bar_format): 

641 bar_format = str(bar_format) 

642 res = bar_format.format(bar=full_bar, **format_dict) 

643 return disp_trim(res, ncols) if ncols else res 

644 

645 elif bar_format: 

646 # user-specified bar_format but no total 

647 l_bar += '|' 

648 format_dict.update(l_bar=l_bar, percentage=0) 

649 full_bar = FormatReplace() 

650 nobar = bar_format.format(bar=full_bar, **format_dict) 

651 if not full_bar.format_called: 

652 return disp_trim(nobar, ncols) if ncols else nobar 

653 full_bar = Bar(0, 

654 max(1, ncols - disp_len(nobar)) if ncols else 10, 

655 charset=Bar.BLANK, colour=colour) 

656 res = bar_format.format(bar=full_bar, **format_dict) 

657 return disp_trim(res, ncols) if ncols else res 

658 else: 

659 # no total: no bar & ETA, just progress stats 

660 res = (f'{(prefix + ": ") if prefix else ""}' 

661 f'{n_fmt}{unit} [{elapsed_str}, {rate_fmt}{postfix}]') 

662 return disp_trim(res, ncols) if ncols else res 

663 

664 def __new__(cls, *_, **__): 

665 instance = object.__new__(cls) 

666 with cls.get_lock(): # also constructs lock if non-existent 

667 cls._instances.add(instance) 

668 # create monitoring thread 

669 if cls.monitor_interval and (cls.monitor is None 

670 or not cls.monitor.report()): 

671 try: 

672 cls.monitor = TMonitor(cls, cls.monitor_interval) 

673 except Exception as e: # pragma: nocover 

674 warn("tqdm:disabling monitor support" 

675 " (monitor_interval = 0) due to:\n" + str(e), 

676 TqdmMonitorWarning, stacklevel=2) 

677 cls.monitor_interval = 0 

678 return instance 

679 

680 @classmethod 

681 def _get_free_pos(cls, instance=None): 

682 """Skips specified instance.""" 

683 positions = {abs(inst.pos) for inst in cls._instances 

684 if inst is not instance and hasattr(inst, "pos")} 

685 return min(set(range(len(positions) + 1)).difference(positions)) 

686 

687 @classmethod 

688 def _decr_instances(cls, instance): 

689 """ 

690 Remove from list and reposition another unfixed bar 

691 to fill the new gap. 

692 

693 This means that by default (where all nested bars are unfixed), 

694 order is not maintained but screen flicker/blank space is minimised. 

695 (tqdm<=4.44.1 moved ALL subsequent unfixed bars up.) 

696 """ 

697 with cls._lock: 

698 try: 

699 cls._instances.remove(instance) 

700 except KeyError: 

701 # if not instance.gui: # pragma: no cover 

702 # raise 

703 pass # py2: maybe magically removed already 

704 # else: 

705 if not instance.gui: 

706 last = (instance.nrows or 20) - 1 

707 # find unfixed (`pos >= 0`) overflow (`pos >= nrows - 1`) 

708 instances = list(filter( 

709 lambda i: hasattr(i, "pos") and last <= i.pos, 

710 cls._instances)) 

711 # set first found to current `pos` 

712 if instances: 

713 inst = min(instances, key=lambda i: i.pos) 

714 inst.clear(nolock=True) 

715 inst.pos = abs(instance.pos) 

716 

717 @classmethod 

718 def write(cls, s, file=None, end="\n", nolock=False): 

719 """Print a message via tqdm (without overlap with bars).""" 

720 fp = file if file is not None else sys.stdout 

721 if fp is None: 

722 return 

723 with cls.external_write_mode(file=file, nolock=nolock): 

724 # Write the message 

725 fp.write(s) 

726 fp.write(end) 

727 

728 @classmethod 

729 @contextmanager 

730 def external_write_mode(cls, file=None, nolock=False): 

731 """ 

732 Disable tqdm within context and refresh tqdm when exits. 

733 Useful when writing to standard output stream 

734 """ 

735 fp = file if file is not None else sys.stdout 

736 if fp is None: 

737 yield 

738 return 

739 

740 try: 

741 if not nolock: 

742 cls.get_lock().acquire() 

743 # Clear all bars 

744 inst_cleared = [] 

745 for inst in getattr(cls, '_instances', []): 

746 # Clear instance if in the target output file 

747 # or if write output + tqdm output are both either 

748 # sys.stdout or sys.stderr (because both are mixed in terminal) 

749 if hasattr(inst, "start_t") and (inst.fp == fp or all( 

750 f in (sys.stdout, sys.stderr) for f in (fp, inst.fp))): 

751 inst.clear(nolock=True) 

752 inst_cleared.append(inst) 

753 yield 

754 # Force refresh display of bars we cleared 

755 for inst in inst_cleared: 

756 inst.refresh(nolock=True) 

757 finally: 

758 if not nolock: 

759 cls._lock.release() 

760 

761 @classmethod 

762 def set_lock(cls, lock): 

763 """Set the global lock.""" 

764 cls._lock = lock 

765 

766 @classmethod 

767 def get_lock(cls): 

768 """Get the global lock. Construct it if it does not exist.""" 

769 if not hasattr(cls, '_lock'): 

770 cls._lock = TqdmDefaultWriteLock() 

771 return cls._lock 

772 

773 @classmethod 

774 def pandas(cls, **tqdm_kwargs): 

775 """ 

776 Registers the current `tqdm` class with 

777 pandas.core. 

778 ( frame.DataFrame 

779 | series.Series 

780 | groupby.(generic.)DataFrameGroupBy 

781 | groupby.(generic.)SeriesGroupBy 

782 ).progress_apply 

783 

784 A new instance will be created every time `progress_apply` is called, 

785 and each instance will automatically `close()` upon completion. 

786 

787 Parameters 

788 ---------- 

789 tqdm_kwargs : arguments for the tqdm instance 

790 

791 Examples 

792 -------- 

793 >>> import pandas as pd 

794 >>> import numpy as np 

795 >>> from tqdm import tqdm 

796 >>> from tqdm.gui import tqdm as tqdm_gui 

797 >>> 

798 >>> df = pd.DataFrame(np.random.randint(0, 100, (100000, 6))) 

799 >>> tqdm.pandas(ncols=50) # can use tqdm_gui, optional kwargs, etc 

800 >>> # Now you can use `progress_apply` instead of `apply` 

801 >>> df.groupby(0).progress_apply(lambda x: x**2) 

802 

803 References 

804 ---------- 

805 <https://stackoverflow.com/questions/18603270/\ 

806 progress-indicator-during-pandas-operations-python> 

807 """ 

808 from warnings import catch_warnings, simplefilter 

809 

810 from pandas.core.frame import DataFrame 

811 from pandas.core.series import Series 

812 try: 

813 with catch_warnings(): 

814 simplefilter("ignore", category=FutureWarning) 

815 from pandas import Panel 

816 except ImportError: # pandas>=1.2.0 

817 Panel = None 

818 Rolling, Expanding = None, None 

819 try: # pandas>=1.0.0 

820 from pandas.core.window.rolling import _Rolling_and_Expanding 

821 except ImportError: 

822 try: # pandas>=0.18.0 

823 from pandas.core.window import _Rolling_and_Expanding 

824 except ImportError: # pandas>=1.2.0 

825 try: # pandas>=1.2.0 

826 from pandas.core.window.expanding import Expanding 

827 from pandas.core.window.rolling import Rolling 

828 _Rolling_and_Expanding = Rolling, Expanding 

829 except ImportError: # pragma: no cover 

830 _Rolling_and_Expanding = None 

831 try: # pandas>=0.25.0 

832 from pandas.core.groupby.generic import SeriesGroupBy # , NDFrameGroupBy 

833 from pandas.core.groupby.generic import DataFrameGroupBy 

834 except ImportError: # pragma: no cover 

835 try: # pandas>=0.23.0 

836 from pandas.core.groupby.groupby import DataFrameGroupBy, SeriesGroupBy 

837 except ImportError: 

838 from pandas.core.groupby import DataFrameGroupBy, SeriesGroupBy 

839 try: # pandas>=0.23.0 

840 from pandas.core.groupby.groupby import GroupBy 

841 except ImportError: # pragma: no cover 

842 from pandas.core.groupby import GroupBy 

843 

844 try: # pandas>=0.23.0 

845 from pandas.core.groupby.groupby import PanelGroupBy 

846 except ImportError: 

847 try: 

848 from pandas.core.groupby import PanelGroupBy 

849 except ImportError: # pandas>=0.25.0 

850 PanelGroupBy = None 

851 

852 tqdm_kwargs = tqdm_kwargs.copy() 

853 deprecated_t = [tqdm_kwargs.pop('deprecated_t', None)] 

854 

855 def inner_generator(df_function='apply'): 

856 def inner(df, func, *args, **kwargs): 

857 """ 

858 Parameters 

859 ---------- 

860 df : (DataFrame|Series)[GroupBy] 

861 Data (may be grouped). 

862 func : function 

863 To be applied on the (grouped) data. 

864 **kwargs : optional 

865 Transmitted to `df.apply()`. 

866 """ 

867 

868 # Precompute total iterations 

869 total = tqdm_kwargs.pop("total", getattr(df, 'ngroups', None)) 

870 if total is None: # not grouped 

871 if df_function == 'applymap': 

872 total = df.size 

873 elif isinstance(df, Series): 

874 total = len(df) 

875 elif (_Rolling_and_Expanding is None or 

876 not isinstance(df, _Rolling_and_Expanding)): 

877 # DataFrame or Panel 

878 axis = kwargs.get('axis', 0) 

879 if axis == 'index': 

880 axis = 0 

881 elif axis == 'columns': 

882 axis = 1 

883 # when axis=0, total is shape[axis1] 

884 total = df.size // df.shape[axis] 

885 

886 # Init bar 

887 if deprecated_t[0] is not None: 

888 t = deprecated_t[0] 

889 deprecated_t[0] = None 

890 else: 

891 t = cls(total=total, **tqdm_kwargs) 

892 

893 if len(args) > 0: 

894 # *args intentionally not supported (see #244, #299) 

895 TqdmDeprecationWarning( 

896 "Except func, normal arguments are intentionally" + 

897 " not supported by" + 

898 " `(DataFrame|Series|GroupBy).progress_apply`." + 

899 " Use keyword arguments instead.", 

900 fp_write=getattr(t.fp, 'write', sys.stderr.write)) 

901 

902 try: # pandas>=1.3.0,<3.0 

903 from pandas.core.common import is_builtin_func 

904 except ImportError: # pandas<1.3.0 

905 is_builtin_func = getattr(df, '_is_builtin_func', lambda f: f) 

906 try: 

907 func = is_builtin_func(func) 

908 except TypeError: 

909 pass 

910 

911 # Define bar updating wrapper 

912 def wrapper(*args, **kwargs): 

913 # update tbar correctly 

914 # it seems `pandas apply` calls `func` twice 

915 # on the first column/row to decide whether it can 

916 # take a fast or slow code path; so stop when t.total==t.n 

917 t.update(n=1 if not t.total or t.n < t.total else 0) 

918 return func(*args, **kwargs) 

919 

920 # Apply the provided function (in **kwargs) 

921 # on the df using our wrapper (which provides bar updating) 

922 try: 

923 return getattr(df, df_function)(wrapper, **kwargs) 

924 finally: 

925 t.close() 

926 

927 return inner 

928 

929 # Monkeypatch pandas to provide easy methods 

930 # Enable custom tqdm progress in pandas! 

931 Series.progress_apply = inner_generator() 

932 SeriesGroupBy.progress_apply = inner_generator() 

933 Series.progress_map = inner_generator('map') 

934 SeriesGroupBy.progress_map = inner_generator('map') 

935 

936 DataFrame.progress_apply = inner_generator() 

937 DataFrameGroupBy.progress_apply = inner_generator() 

938 DataFrame.progress_applymap = inner_generator('applymap') 

939 DataFrame.progress_map = inner_generator('map') 

940 DataFrameGroupBy.progress_map = inner_generator('map') 

941 

942 if Panel is not None: 

943 Panel.progress_apply = inner_generator() 

944 if PanelGroupBy is not None: 

945 PanelGroupBy.progress_apply = inner_generator() 

946 

947 GroupBy.progress_apply = inner_generator() 

948 GroupBy.progress_aggregate = inner_generator('aggregate') 

949 GroupBy.progress_transform = inner_generator('transform') 

950 

951 if Rolling is not None and Expanding is not None: 

952 Rolling.progress_apply = inner_generator() 

953 Expanding.progress_apply = inner_generator() 

954 elif _Rolling_and_Expanding is not None: 

955 _Rolling_and_Expanding.progress_apply = inner_generator() 

956 

957 # override defaults via env vars 

958 @envwrap("tqdm", is_method=True, types={'total': float, 'ncols': int, 'miniters': float, 

959 'position': int, 'nrows': int}) 

960 def __init__(self, iterable=None, desc=None, total=None, leave=True, file=None, 

961 ncols=None, mininterval=0.1, maxinterval=10.0, miniters=None, 

962 ascii=None, # pylint: disable=redefined-builtin 

963 disable=False, unit='it', unit_scale=False, dynamic_ncols=False, smoothing=0.3, 

964 bar_format=None, initial=0, position=None, postfix=None, unit_divisor=1000, 

965 write_bytes=False, lock_args=None, nrows=None, colour=None, delay=0.0, gui=False, 

966 **kwargs): 

967 """see tqdm.tqdm for arguments""" 

968 if file is None: 

969 file = sys.stderr 

970 

971 if write_bytes: 

972 # Despite coercing unicode into bytes, py2 sys.std* streams 

973 # should have bytes written to them. 

974 file = SimpleTextIOWrapper( 

975 file, encoding=getattr(file, 'encoding', None) or 'utf-8') 

976 

977 file = DisableOnWriteError(file, tqdm_instance=self) 

978 

979 if disable is None and hasattr(file, "isatty") and not file.isatty(): 

980 disable = True 

981 

982 if total is None and iterable is not None: 

983 try: 

984 total = len(iterable) 

985 except (TypeError, AttributeError): 

986 total = None 

987 if total == float("inf"): 

988 total = None # same as unknown 

989 

990 if disable: 

991 self.iterable = iterable 

992 self.disable = disable 

993 with self._lock: 

994 self.pos = self._get_free_pos(self) 

995 self._instances.remove(self) 

996 self.n = initial 

997 self.total = total 

998 self.leave = leave 

999 return 

1000 

1001 if kwargs: 

1002 self.disable = True 

1003 with self._lock: 

1004 self.pos = self._get_free_pos(self) 

1005 self._instances.remove(self) 

1006 raise ( 

1007 TqdmDeprecationWarning( 

1008 "`nested` is deprecated and automated.\n" 

1009 "Use `position` instead for manual control.\n", 

1010 fp_write=getattr(file, 'write', sys.stderr.write)) 

1011 if "nested" in kwargs else 

1012 TqdmKeyError("Unknown argument(s): " + str(kwargs))) 

1013 

1014 # Preprocess the arguments 

1015 if ( 

1016 (ncols is None or nrows is None) and (file in (sys.stderr, sys.stdout)) 

1017 ) or dynamic_ncols: # pragma: no cover 

1018 if dynamic_ncols: 

1019 dynamic_ncols = _screen_shape_wrapper() 

1020 if dynamic_ncols: 

1021 ncols, nrows = dynamic_ncols(file) 

1022 else: 

1023 _dynamic_ncols = _screen_shape_wrapper() 

1024 if _dynamic_ncols: 

1025 _ncols, _nrows = _dynamic_ncols(file) 

1026 if ncols is None: 

1027 ncols = _ncols 

1028 if nrows is None: 

1029 nrows = _nrows 

1030 

1031 if miniters is None: 

1032 miniters = 0 

1033 dynamic_miniters = True 

1034 else: 

1035 dynamic_miniters = False 

1036 

1037 if mininterval is None: 

1038 mininterval = 0 

1039 

1040 if maxinterval is None: 

1041 maxinterval = 0 

1042 

1043 if ascii is None: 

1044 ascii = not _supports_unicode(file) 

1045 

1046 if bar_format and ascii is not True and not _is_ascii(ascii): 

1047 # Convert bar format into unicode since terminal uses unicode 

1048 bar_format = str(bar_format) 

1049 

1050 if smoothing is None: 

1051 smoothing = 0 

1052 

1053 # Store the arguments 

1054 self.iterable = iterable 

1055 self.desc = desc or '' 

1056 self.total = total 

1057 self.leave = leave 

1058 self.fp = file 

1059 self.ncols = ncols 

1060 self.nrows = nrows 

1061 self.mininterval = mininterval 

1062 self.maxinterval = maxinterval 

1063 self.miniters = miniters 

1064 self.dynamic_miniters = dynamic_miniters 

1065 self.ascii = ascii 

1066 self.disable = disable 

1067 self.unit = unit 

1068 self.unit_scale = unit_scale 

1069 self.unit_divisor = unit_divisor 

1070 self.initial = initial 

1071 self.lock_args = lock_args 

1072 self.delay = delay 

1073 self.gui = gui 

1074 self.dynamic_ncols = dynamic_ncols 

1075 self.smoothing = smoothing 

1076 self._ema_dn = EMA(smoothing) 

1077 self._ema_dt = EMA(smoothing) 

1078 self._ema_miniters = EMA(smoothing) 

1079 self.bar_format = bar_format 

1080 self.postfix = None 

1081 self.colour = colour 

1082 self._time = time 

1083 if postfix: 

1084 try: 

1085 self.set_postfix(refresh=False, **postfix) 

1086 except TypeError: 

1087 self.postfix = postfix 

1088 

1089 # Init the iterations counters 

1090 self.last_print_n = initial 

1091 self.n = initial 

1092 

1093 # if nested, at initial sp() call we replace '\r' by '\n' to 

1094 # not overwrite the outer progress bar 

1095 with self._lock: 

1096 # mark fixed positions as negative 

1097 self.pos = self._get_free_pos(self) if position is None else -position 

1098 

1099 if not gui: 

1100 # Initialize the screen printer 

1101 self.sp = self.status_printer(self.fp) 

1102 if delay <= 0: 

1103 self.refresh(lock_args=self.lock_args) 

1104 

1105 # Init the time counter 

1106 self.last_print_t = self._time() 

1107 # NB: Avoid race conditions by setting start_t at the very end of init 

1108 self.start_t = self.last_print_t 

1109 

1110 def __bool__(self): 

1111 if self.total is not None: 

1112 return self.total > 0 

1113 if self.iterable is None: 

1114 raise TypeError('bool() undefined when iterable == total == None') 

1115 return bool(self.iterable) 

1116 

1117 def __len__(self): 

1118 return ( 

1119 self.total if self.iterable is None 

1120 else self.iterable.shape[0] if hasattr(self.iterable, "shape") 

1121 else len(self.iterable) if hasattr(self.iterable, "__len__") 

1122 else self.iterable.__length_hint__() if hasattr(self.iterable, "__length_hint__") 

1123 else getattr(self, "total", None)) 

1124 

1125 def __reversed__(self): 

1126 try: 

1127 orig = self.iterable 

1128 except AttributeError: 

1129 raise TypeError("'tqdm' object is not reversible") 

1130 else: 

1131 self.iterable = reversed(self.iterable) 

1132 return self.__iter__() 

1133 finally: 

1134 self.iterable = orig 

1135 

1136 def __contains__(self, item): 

1137 contains = getattr(self.iterable, '__contains__', None) 

1138 return (contains(item) if contains is not None # pylint: disable=not-callable 

1139 else item in self.__iter__()) 

1140 

1141 def __enter__(self): 

1142 return self 

1143 

1144 def __exit__(self, exc_type, exc_value, traceback): 

1145 try: 

1146 self.close() 

1147 except AttributeError: 

1148 # maybe eager thread cleanup upon external error 

1149 if (exc_type, exc_value, traceback) == (None, None, None): 

1150 raise 

1151 warn("AttributeError ignored", TqdmWarning, stacklevel=2) 

1152 

1153 def __del__(self): 

1154 self.close() 

1155 

1156 def __str__(self): 

1157 return self.format_meter(**self.format_dict) 

1158 

1159 @property 

1160 def _comparable(self): 

1161 return abs(getattr(self, "pos", 1 << 31)) 

1162 

1163 def __hash__(self): 

1164 return id(self) 

1165 

1166 def __iter__(self): 

1167 """Backward-compatibility to use: for x in tqdm(iterable)""" 

1168 

1169 # Inlining instance variables as locals (speed optimisation) 

1170 iterable = self.iterable 

1171 

1172 # If the bar is disabled, then just walk the iterable 

1173 # (note: keep this check outside the loop for performance) 

1174 if self.disable: 

1175 for obj in iterable: 

1176 yield obj 

1177 return 

1178 

1179 mininterval = self.mininterval 

1180 last_print_t = self.last_print_t 

1181 last_print_n = self.last_print_n 

1182 min_start_t = self.start_t + self.delay 

1183 n = self.n 

1184 time = self._time 

1185 

1186 try: 

1187 for obj in iterable: 

1188 yield obj 

1189 # Update and possibly print the progress bar. 

1190 # Note: does not call self.update(1) for speed optimisation. 

1191 n += 1 

1192 

1193 if n - last_print_n >= self.miniters: 

1194 cur_t = time() 

1195 dt = cur_t - last_print_t 

1196 if dt >= mininterval and cur_t >= min_start_t: 

1197 self.update(n - last_print_n) 

1198 last_print_n = self.last_print_n 

1199 last_print_t = self.last_print_t 

1200 finally: 

1201 self.n = n 

1202 self.close() 

1203 

1204 def update(self, n=1): 

1205 """ 

1206 Manually update the progress bar, useful for streams 

1207 such as reading files. 

1208 E.g.: 

1209 >>> t = tqdm(total=filesize) # Initialise 

1210 >>> for current_buffer in stream: 

1211 ... ... 

1212 ... t.update(len(current_buffer)) 

1213 >>> t.close() 

1214 The last line is highly recommended, but possibly not necessary if 

1215 `t.update()` will be called in such a way that `filesize` will be 

1216 exactly reached and printed. 

1217 

1218 Parameters 

1219 ---------- 

1220 n : int or float, optional 

1221 Increment to add to the internal counter of iterations 

1222 [default: 1]. If using float, consider specifying `{n:.3f}` 

1223 or similar in `bar_format`, or specifying `unit_scale`. 

1224 

1225 Returns 

1226 ------- 

1227 out : bool or None 

1228 True if a `display()` was triggered. 

1229 """ 

1230 if self.disable: 

1231 return 

1232 

1233 if n < 0: 

1234 self.last_print_n += n # for auto-refresh logic to work 

1235 self.n += n 

1236 

1237 # check counter first to reduce calls to time() 

1238 if self.n - self.last_print_n >= self.miniters: 

1239 cur_t = self._time() 

1240 dt = cur_t - self.last_print_t 

1241 if dt >= self.mininterval and cur_t >= self.start_t + self.delay: 

1242 cur_t = self._time() 

1243 dn = self.n - self.last_print_n # >= n 

1244 if self.smoothing and dt and dn: 

1245 # EMA (not just overall average) 

1246 self._ema_dn(dn) 

1247 self._ema_dt(dt) 

1248 self.refresh(lock_args=self.lock_args) 

1249 if self.dynamic_miniters: 

1250 # If no `miniters` was specified, adjust automatically to the 

1251 # maximum iteration rate seen so far between two prints. 

1252 # e.g.: After running `tqdm.update(5)`, subsequent 

1253 # calls to `tqdm.update()` will only cause an update after 

1254 # at least 5 more iterations. 

1255 if self.maxinterval and dt >= self.maxinterval: 

1256 self.miniters = dn * (self.mininterval or self.maxinterval) / dt 

1257 elif self.smoothing: 

1258 # EMA miniters update 

1259 self.miniters = self._ema_miniters( 

1260 dn * (self.mininterval / dt if self.mininterval and dt 

1261 else 1)) 

1262 else: 

1263 # max iters between two prints 

1264 self.miniters = max(self.miniters, dn) 

1265 

1266 # Store old values for next call 

1267 self.last_print_n = self.n 

1268 self.last_print_t = cur_t 

1269 return True 

1270 

1271 def close(self): 

1272 """Cleanup and (if leave=False) close the progress bar.""" 

1273 if getattr(self, 'disable', True): 

1274 return 

1275 

1276 # Prevent multiple closures 

1277 self.disable = True 

1278 

1279 # decrement instance pos and remove from internal set 

1280 pos = abs(self.pos) 

1281 self._decr_instances(self) 

1282 

1283 if not hasattr(self, 'last_print_t'): 

1284 return 

1285 if self.last_print_t < self.start_t + self.delay: 

1286 # haven't ever displayed; nothing to clear 

1287 return 

1288 

1289 # GUI mode 

1290 if getattr(self, 'sp', None) is None: 

1291 return 

1292 

1293 # annoyingly, _supports_unicode isn't good enough 

1294 def fp_write(s): 

1295 self.fp.write(str(s)) 

1296 

1297 try: 

1298 fp_write('') 

1299 except ValueError as e: 

1300 if 'closed' in str(e): 

1301 return 

1302 raise # pragma: no cover 

1303 

1304 leave = pos == 0 if self.leave is None else self.leave 

1305 

1306 with self._lock: 

1307 if leave: 

1308 # stats for overall rate (no weighted average) 

1309 self._ema_dt = lambda: None 

1310 self.display(pos=0) 

1311 fp_write('\n') 

1312 else: 

1313 # clear previous display 

1314 if self.display(msg='', pos=pos) and not pos: 

1315 fp_write('\r') 

1316 

1317 def clear(self, nolock=False): 

1318 """Clear current bar display.""" 

1319 if self.disable: 

1320 return 

1321 

1322 if not nolock: 

1323 self._lock.acquire() 

1324 pos = abs(self.pos) 

1325 if pos < (self.nrows or 20): 

1326 self.moveto(pos) 

1327 self.sp('') 

1328 self.fp.write('\r') # place cursor back at the beginning of line 

1329 self.moveto(-pos) 

1330 if not nolock: 

1331 self._lock.release() 

1332 

1333 def refresh(self, nolock=False, lock_args=None): 

1334 """ 

1335 Force refresh the display of this bar. 

1336 

1337 Parameters 

1338 ---------- 

1339 nolock : bool, optional 

1340 If `True`, does not lock. 

1341 If [default: `False`]: calls `acquire()` on internal lock. 

1342 lock_args : tuple, optional 

1343 Passed to internal lock's `acquire()`. 

1344 If specified, will only `display()` if `acquire()` returns `True`. 

1345 """ 

1346 if self.disable: 

1347 return 

1348 

1349 if not nolock: 

1350 if lock_args: 

1351 if not self._lock.acquire(*lock_args): 

1352 return False 

1353 else: 

1354 self._lock.acquire() 

1355 self.display() 

1356 if not nolock: 

1357 self._lock.release() 

1358 return True 

1359 

1360 def unpause(self): 

1361 """Restart tqdm timer from last print time.""" 

1362 if self.disable: 

1363 return 

1364 cur_t = self._time() 

1365 self.start_t += cur_t - self.last_print_t 

1366 self.last_print_t = cur_t 

1367 

1368 def reset(self, total=None): 

1369 """ 

1370 Resets to 0 iterations for repeated use. 

1371 

1372 Consider combining with `leave=True`. 

1373 

1374 Parameters 

1375 ---------- 

1376 total : int or float, optional. Total to use for the new bar. 

1377 """ 

1378 self.n = 0 

1379 if total is not None: 

1380 self.total = None if total == float("inf") else total 

1381 if self.disable: 

1382 return 

1383 self.last_print_n = 0 

1384 self.last_print_t = self.start_t = self._time() 

1385 self._ema_dn = EMA(self.smoothing) 

1386 self._ema_dt = EMA(self.smoothing) 

1387 self._ema_miniters = EMA(self.smoothing) 

1388 self.refresh() 

1389 

1390 def set_description(self, desc=None, refresh=True): 

1391 """ 

1392 Set/modify description of the progress bar. 

1393 

1394 Parameters 

1395 ---------- 

1396 desc : str, optional 

1397 refresh : bool, optional 

1398 Forces refresh [default: True]. 

1399 """ 

1400 self.desc = desc + ': ' if desc else '' 

1401 if refresh: 

1402 self.refresh() 

1403 

1404 def set_description_str(self, desc=None, refresh=True): 

1405 """Set/modify description without ': ' appended.""" 

1406 self.desc = desc or '' 

1407 if refresh: 

1408 self.refresh() 

1409 

1410 def set_postfix(self, ordered_dict=None, refresh=True, **kwargs): 

1411 """ 

1412 Set/modify postfix (additional stats) 

1413 with automatic formatting based on datatype. 

1414 

1415 Parameters 

1416 ---------- 

1417 ordered_dict : dict or OrderedDict, optional 

1418 refresh : bool, optional 

1419 Forces refresh [default: True]. 

1420 kwargs : dict, optional 

1421 """ 

1422 # Sort in alphabetical order to be more deterministic 

1423 postfix = OrderedDict([] if ordered_dict is None else ordered_dict) 

1424 for key in sorted(kwargs.keys()): 

1425 postfix[key] = kwargs[key] 

1426 # Preprocess stats according to datatype 

1427 for key in postfix.keys(): 

1428 # Number: limit the length of the string 

1429 if isinstance(postfix[key], Number): 

1430 postfix[key] = self.format_num(postfix[key]) 

1431 # Else for any other type, try to get the string conversion 

1432 elif not isinstance(postfix[key], str): 

1433 postfix[key] = str(postfix[key]) 

1434 # Else if it's a string, don't need to preprocess anything 

1435 # Stitch together to get the final postfix 

1436 self.postfix = ', '.join(key + '=' + postfix[key].strip() 

1437 for key in postfix.keys()) 

1438 if refresh: 

1439 self.refresh() 

1440 

1441 def set_postfix_str(self, s='', refresh=True): 

1442 """ 

1443 Postfix without dictionary expansion, similar to prefix handling. 

1444 """ 

1445 self.postfix = str(s) 

1446 if refresh: 

1447 self.refresh() 

1448 

1449 def moveto(self, n): 

1450 # TODO: private method 

1451 self.fp.write('\n' * n + _term_move_up() * -n) 

1452 getattr(self.fp, 'flush', lambda: None)() 

1453 

1454 @property 

1455 def format_dict(self): 

1456 """Public API for read-only member access.""" 

1457 if self.disable and not hasattr(self, 'unit'): 

1458 return defaultdict(lambda: None, { 

1459 'n': self.n, 'total': self.total, 'elapsed': 0, 'unit': 'it'}) 

1460 if self.dynamic_ncols: 

1461 self.ncols, self.nrows = self.dynamic_ncols(self.fp) 

1462 return { 

1463 'n': self.n, 'total': self.total, 

1464 'elapsed': self._time() - self.start_t if hasattr(self, 'start_t') else 0, 

1465 'ncols': self.ncols, 'nrows': self.nrows, 'prefix': self.desc, 

1466 'ascii': self.ascii, 'unit': self.unit, 'unit_scale': self.unit_scale, 

1467 'rate': self._ema_dn() / self._ema_dt() if self._ema_dt() else None, 

1468 'bar_format': self.bar_format, 'postfix': self.postfix, 

1469 'unit_divisor': self.unit_divisor, 'initial': self.initial, 

1470 'colour': self.colour} 

1471 

1472 def display(self, msg=None, pos=None): 

1473 """ 

1474 Use `self.sp` to display `msg` in the specified `pos`. 

1475 

1476 Consider overloading this function when inheriting to use e.g.: 

1477 `self.some_frontend(**self.format_dict)` instead of `self.sp`. 

1478 

1479 Parameters 

1480 ---------- 

1481 msg : str, optional. What to display (default: `repr(self)`). 

1482 pos : int, optional. Position to `moveto` 

1483 (default: `abs(self.pos)`). 

1484 """ 

1485 if pos is None: 

1486 pos = abs(self.pos) 

1487 

1488 nrows = self.nrows or 20 

1489 if pos >= nrows - 1: 

1490 if pos >= nrows: 

1491 return False 

1492 if msg or msg is None: # override at `nrows - 1` 

1493 msg = " ... (more hidden) ..." 

1494 

1495 if not hasattr(self, "sp"): 

1496 raise TqdmDeprecationWarning( 

1497 "Please use `tqdm.gui.tqdm(...)`" 

1498 " instead of `tqdm(..., gui=True)`\n", 

1499 fp_write=getattr(self.fp, 'write', sys.stderr.write)) 

1500 

1501 if pos: 

1502 self.moveto(pos) 

1503 self.sp(self.__str__() if msg is None else msg) 

1504 if pos: 

1505 self.moveto(-pos) 

1506 return True 

1507 

1508 @classmethod 

1509 @contextmanager 

1510 def wrapattr(cls, stream, method, total=None, bytes=True, # pylint: disable=redefined-builtin 

1511 **tqdm_kwargs): 

1512 """ 

1513 stream : file-like object. 

1514 method : str, "read" or "write". The result of `read()` and 

1515 the first argument of `write()` should have a `len()`. 

1516 

1517 >>> with tqdm.wrapattr(file_obj, "read", total=file_obj.size) as fobj: 

1518 ... while True: 

1519 ... chunk = fobj.read(chunk_size) 

1520 ... if not chunk: 

1521 ... break 

1522 """ 

1523 with cls(total=total, **tqdm_kwargs) as t: 

1524 if bytes: 

1525 t.unit = "B" 

1526 t.unit_scale = True 

1527 t.unit_divisor = 1024 

1528 yield CallbackIOWrapper(t.update, stream, method) 

1529 

1530 

1531def trange(*args, **kwargs): 

1532 """Shortcut for tqdm(range(*args), **kwargs).""" 

1533 return tqdm(range(*args), **kwargs)