1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """Text progressbar library for python.
23
24 This library provides a text mode progressbar. This is tipically used
25 to display the progress of a long running operation, providing a
26 visual clue that processing is underway.
27
28 The ProgressBar class manages the progress, and the format of the line
29 is given by a number of widgets. A widget is an object that may
30 display diferently depending on the state of the progress. There are
31 three types of widget:
32 - a string, which always shows itself;
33 - a ProgressBarWidget, which may return a diferent value every time
34 it's update method is called; and
35 - a ProgressBarWidgetHFill, which is like ProgressBarWidget, except it
36 expands to fill the remaining width of the line.
37
38 The progressbar module is very easy to use, yet very powerful. And
39 automatically supports features like auto-resizing when available.
40 """
41
42 from __future__ import absolute_import
43 from __future__ import print_function
44 import six
45 from six.moves import range
46 __author__ = "Nilton Volpato"
47 __author_email__ = "first-name dot last-name @ gmail.com"
48 __date__ = "2006-05-07"
49 __version__ = "2.2"
50
51
52
53
54
55
56
57
58
59
60
61 import sys, time
62 from array import array
63 try:
64 from fcntl import ioctl
65 import termios
66 except ImportError:
67 pass
68 import signal
69
86
106
107
108 -class ETA(ProgressBarWidget):
109 "Widget for the Estimated Time of Arrival"
113 if pbar.currval == 0:
114 return 'ETA: --:--:--'
115 elif pbar.finished:
116 return 'Time: %s' % self.format_time(pbar.seconds_elapsed)
117 else:
118 elapsed = pbar.seconds_elapsed
119 eta = elapsed * pbar.maxval / pbar.currval - elapsed
120 return 'ETA: %s' % self.format_time(eta)
121
123 "Widget for showing the transfer speed (useful for file transfers)."
125 self.fmt = '%6.2f %s'
126 self.units = ['B','K','M','G','T','P']
128 if pbar.seconds_elapsed < 2e-6:
129 bps = 0.0
130 else:
131 bps = float(pbar.currval) / pbar.seconds_elapsed
132 spd = bps
133 for u in self.units:
134 if spd < 1000:
135 break
136 spd /= 1000
137 return self.fmt % (spd, u+'/s')
138
140 "A rotating marker for filling the bar of progress."
142 self.markers = markers
143 self.curmark = -1
145 if pbar.finished:
146 return self.markers[0]
147 self.curmark = (self.curmark + 1)%len(self.markers)
148 return self.markers[self.curmark]
149
151 "Just the percentage done."
154
155 -class Bar(ProgressBarWidgetHFill):
156 "The bar of progress. It will strech to fill the line."
157 - def __init__(self, marker='#', left='|', right='|'):
158 self.marker = marker
159 self.left = left
160 self.right = right
166 - def update(self, pbar, width):
167 percent = pbar.percentage()
168 cwidth = width - len(self.left) - len(self.right)
169 marked_width = int(percent * cwidth / 100)
170 m = self._format_marker(pbar)
171 bar = (self.left + (m*marked_width).ljust(cwidth) + self.right)
172 return bar
173
175 "The reverse bar of progress, or bar of regress. :)"
176 - def update(self, pbar, width):
177 percent = pbar.percentage()
178 cwidth = width - len(self.left) - len(self.right)
179 marked_width = int(percent * cwidth / 100)
180 m = self._format_marker(pbar)
181 bar = (self.left + (m*marked_width).rjust(cwidth) + self.right)
182 return bar
183
184 default_widgets = [Percentage(), ' ', Bar()]
186 """This is the ProgressBar class, it updates and prints the bar.
187
188 The term_width parameter may be an integer. Or None, in which case
189 it will try to guess it, if it fails it will default to 80 columns.
190
191 The simple use is like this:
192 >>> pbar = ProgressBar().start()
193 >>> for i in xrange(100):
194 ... # do something
195 ... pbar.update(i+1)
196 ...
197 >>> pbar.finish()
198
199 But anything you want to do is possible (well, almost anything).
200 You can supply different widgets of any type in any order. And you
201 can even write your own widgets! There are many widgets already
202 shipped and you should experiment with them.
203
204 When implementing a widget update method you may access any
205 attribute or function of the ProgressBar object calling the
206 widget's update method. The most important attributes you would
207 like to access are:
208 - currval: current value of the progress, 0 <= currval <= maxval
209 - maxval: maximum (and final) value of the progress
210 - finished: True if the bar is have finished (reached 100%), False o/w
211 - start_time: first time update() method of ProgressBar was called
212 - seconds_elapsed: seconds elapsed since start_time
213 - percentage(): percentage of the progress (this is a method)
214 """
217 assert maxval >= 0
218 self.maxval = maxval
219 self.widgets = widgets
220 self.fd = fd
221 self.signal_set = False
222 if term_width is None:
223 try:
224 self.handle_resize(None,None)
225 signal.signal(signal.SIGWINCH, self.handle_resize)
226 self.signal_set = True
227 except Exception:
228 self.term_width = 79
229 else:
230 self.term_width = term_width
231
232 self.currval = 0
233 self.finished = False
234 self.prev_percentage = -1
235 self.start_time = None
236 self.seconds_elapsed = 0
237
239 h,w=array('h', ioctl(self.fd,termios.TIOCGWINSZ,'\0'*8))[:2]
240 self.term_width = w
241
243 "Returns the percentage of the progress."
244 return self.currval*100.0 / self.maxval
245
266
269
271 return int(self.percentage()) != int(self.prev_percentage)
272
274 "Updates the progress bar to a new value."
275 assert 0 <= value <= self.maxval
276 self.currval = value
277 if not self._need_update() or self.finished:
278 return
279 if not self.start_time:
280 self.start_time = time.time()
281 self.seconds_elapsed = time.time() - self.start_time
282 self.prev_percentage = self.percentage()
283 if value != self.maxval:
284 self.fd.write(self._format_line() + '\r')
285 else:
286 self.finished = True
287 self.fd.write(self._format_line() + '\n')
288
290 """Start measuring time, and prints the bar at 0%.
291
292 It returns self so you can use it like this:
293 >>> pbar = ProgressBar().start()
294 >>> for i in xrange(100):
295 ... # do something
296 ... pbar.update(i+1)
297 ...
298 >>> pbar.finish()
299 """
300 self.update(0)
301 return self
302
304 """Used to tell the progress is finished."""
305 self.update(self.maxval)
306 self.fd.flush()
307 if self.signal_set:
308 signal.signal(signal.SIGWINCH, signal.SIG_DFL)
309
310
312
314 """ a practicla definition of a progressbar this one is une in MW"""
315
316 widgets = [name+': ', Percentage(), ' ', Bar('>'),
317 ' ', ETA(), ' ']
318 if max_step:
319 ProgressBar.__init__(self,widgets=widgets, maxval=max_step)
320 self.start()
321 self.maxval=max_step
322 self.actual_step=0
323
325 if value<0:
326 self.actual_step+=1
327 else:
328 self.actual_step=value
329
330 if self.maxval:
331 ProgressBar.update(self,self.actual_step)
332
337
338
339
340 if __name__=='__main__':
341 import os
342 import time
344 widgets = ['ValTest', Percentage(), ' ', Bar(),' ', ETA(), ' ']
345 pbar = ProgressBar(widgets=widgets, maxval=100).start()
346 for i in range(100):
347 time.sleep(0.02)
348
349 pbar.update(1*i+1)
350 pbar.finish()
351 print()
352
362
364 class CrazyFileTransferSpeed(FileTransferSpeed):
365 "It's bigger between 45 and 80 percent"
366 def update(self, pbar):
367 if 45 < pbar.percentage() < 80:
368 return 'Bigger Now ' + FileTransferSpeed.update(self,pbar)
369 else:
370 return FileTransferSpeed.update(self,pbar)
371
372 widgets = [CrazyFileTransferSpeed(),' <<<', Bar(), '>>> ', Percentage(),' ', ETA()]
373 pbar = ProgressBar(widgets=widgets, maxval=10000000)
374
375 pbar.start()
376 for i in range(2000000):
377
378 pbar.update(5*i+1)
379 pbar.finish()
380 print()
381
390
392 widgets = ['Test: ', Percentage(), ' ',
393 Bar(marker='0',left='[',right=']'),
394 ' ', ETA(), ' ', FileTransferSpeed()]
395 pbar = ProgressBar(widgets=widgets, maxval=500)
396 pbar.start()
397 for i in range(100,500+1,50):
398 time.sleep(0.2)
399 pbar.update(i)
400 pbar.finish()
401 print()
402
403 exampleVal()
404 example1()
405 example2()
406 example3()
407 example4()
408