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 __author__ = "Nilton Volpato"
43 __author_email__ = "first-name dot last-name @ gmail.com"
44 __date__ = "2006-05-07"
45 __version__ = "2.2"
46
47
48
49
50
51
52
53
54
55
56
57 import sys, time
58 from array import array
59 try:
60 from fcntl import ioctl
61 import termios
62 except ImportError:
63 pass
64 import signal
65
82
102
103
104 -class ETA(ProgressBarWidget):
105 "Widget for the Estimated Time of Arrival"
109 if pbar.currval == 0:
110 return 'ETA: --:--:--'
111 elif pbar.finished:
112 return 'Time: %s' % self.format_time(pbar.seconds_elapsed)
113 else:
114 elapsed = pbar.seconds_elapsed
115 eta = elapsed * pbar.maxval / pbar.currval - elapsed
116 return 'ETA: %s' % self.format_time(eta)
117
119 "Widget for showing the transfer speed (useful for file transfers)."
121 self.fmt = '%6.2f %s'
122 self.units = ['B','K','M','G','T','P']
124 if pbar.seconds_elapsed < 2e-6:
125 bps = 0.0
126 else:
127 bps = float(pbar.currval) / pbar.seconds_elapsed
128 spd = bps
129 for u in self.units:
130 if spd < 1000:
131 break
132 spd /= 1000
133 return self.fmt % (spd, u+'/s')
134
136 "A rotating marker for filling the bar of progress."
138 self.markers = markers
139 self.curmark = -1
141 if pbar.finished:
142 return self.markers[0]
143 self.curmark = (self.curmark + 1)%len(self.markers)
144 return self.markers[self.curmark]
145
147 "Just the percentage done."
150
151 -class Bar(ProgressBarWidgetHFill):
152 "The bar of progress. It will strech to fill the line."
153 - def __init__(self, marker='#', left='|', right='|'):
154 self.marker = marker
155 self.left = left
156 self.right = right
162 - def update(self, pbar, width):
163 percent = pbar.percentage()
164 cwidth = width - len(self.left) - len(self.right)
165 marked_width = int(percent * cwidth / 100)
166 m = self._format_marker(pbar)
167 bar = (self.left + (m*marked_width).ljust(cwidth) + self.right)
168 return bar
169
171 "The reverse bar of progress, or bar of regress. :)"
172 - def update(self, pbar, width):
173 percent = pbar.percentage()
174 cwidth = width - len(self.left) - len(self.right)
175 marked_width = int(percent * cwidth / 100)
176 m = self._format_marker(pbar)
177 bar = (self.left + (m*marked_width).rjust(cwidth) + self.right)
178 return bar
179
180 default_widgets = [Percentage(), ' ', Bar()]
182 """This is the ProgressBar class, it updates and prints the bar.
183
184 The term_width parameter may be an integer. Or None, in which case
185 it will try to guess it, if it fails it will default to 80 columns.
186
187 The simple use is like this:
188 >>> pbar = ProgressBar().start()
189 >>> for i in xrange(100):
190 ... # do something
191 ... pbar.update(i+1)
192 ...
193 >>> pbar.finish()
194
195 But anything you want to do is possible (well, almost anything).
196 You can supply different widgets of any type in any order. And you
197 can even write your own widgets! There are many widgets already
198 shipped and you should experiment with them.
199
200 When implementing a widget update method you may access any
201 attribute or function of the ProgressBar object calling the
202 widget's update method. The most important attributes you would
203 like to access are:
204 - currval: current value of the progress, 0 <= currval <= maxval
205 - maxval: maximum (and final) value of the progress
206 - finished: True if the bar is have finished (reached 100%), False o/w
207 - start_time: first time update() method of ProgressBar was called
208 - seconds_elapsed: seconds elapsed since start_time
209 - percentage(): percentage of the progress (this is a method)
210 """
213 assert maxval >= 0
214 self.maxval = maxval
215 self.widgets = widgets
216 self.fd = fd
217 self.signal_set = False
218 if term_width is None:
219 try:
220 self.handle_resize(None,None)
221 signal.signal(signal.SIGWINCH, self.handle_resize)
222 self.signal_set = True
223 except Exception:
224 self.term_width = 79
225 else:
226 self.term_width = term_width
227
228 self.currval = 0
229 self.finished = False
230 self.prev_percentage = -1
231 self.start_time = None
232 self.seconds_elapsed = 0
233
235 h,w=array('h', ioctl(self.fd,termios.TIOCGWINSZ,'\0'*8))[:2]
236 self.term_width = w
237
239 "Returns the percentage of the progress."
240 return self.currval*100.0 / self.maxval
241
262
265
267 return int(self.percentage()) != int(self.prev_percentage)
268
270 "Updates the progress bar to a new value."
271 assert 0 <= value <= self.maxval
272 self.currval = value
273 if not self._need_update() or self.finished:
274 return
275 if not self.start_time:
276 self.start_time = time.time()
277 self.seconds_elapsed = time.time() - self.start_time
278 self.prev_percentage = self.percentage()
279 if value != self.maxval:
280 self.fd.write(self._format_line() + '\r')
281 else:
282 self.finished = True
283 self.fd.write(self._format_line() + '\n')
284
286 """Start measuring time, and prints the bar at 0%.
287
288 It returns self so you can use it like this:
289 >>> pbar = ProgressBar().start()
290 >>> for i in xrange(100):
291 ... # do something
292 ... pbar.update(i+1)
293 ...
294 >>> pbar.finish()
295 """
296 self.update(0)
297 return self
298
300 """Used to tell the progress is finished."""
301 self.update(self.maxval)
302 self.fd.flush()
303 if self.signal_set:
304 signal.signal(signal.SIGWINCH, signal.SIG_DFL)
305
306
308
310 """ a practicla definition of a progressbar this one is une in MW"""
311
312 widgets = [name+': ', Percentage(), ' ', Bar('>'),
313 ' ', ETA(), ' ']
314 if max_step:
315 ProgressBar.__init__(self,widgets=widgets, maxval=max_step)
316 self.start()
317 self.maxval=max_step
318 self.actual_step=0
319
321 if value<0:
322 self.actual_step+=1
323 else:
324 self.actual_step=value
325
326 if self.maxval:
327 ProgressBar.update(self,self.actual_step)
328
333
334
335
336 if __name__=='__main__':
337 import os
338 import time
348
358
360 class CrazyFileTransferSpeed(FileTransferSpeed):
361 "It's bigger between 45 and 80 percent"
362 def update(self, pbar):
363 if 45 < pbar.percentage() < 80:
364 return 'Bigger Now ' + FileTransferSpeed.update(self,pbar)
365 else:
366 return FileTransferSpeed.update(self,pbar)
367
368 widgets = [CrazyFileTransferSpeed(),' <<<', Bar(), '>>> ', Percentage(),' ', ETA()]
369 pbar = ProgressBar(widgets=widgets, maxval=10000000)
370
371 pbar.start()
372 for i in range(2000000):
373
374 pbar.update(5*i+1)
375 pbar.finish()
376 print
377
386
388 widgets = ['Test: ', Percentage(), ' ',
389 Bar(marker='0',left='[',right=']'),
390 ' ', ETA(), ' ', FileTransferSpeed()]
391 pbar = ProgressBar(widgets=widgets, maxval=500)
392 pbar.start()
393 for i in range(100,500+1,50):
394 time.sleep(0.2)
395 pbar.update(i)
396 pbar.finish()
397 print
398
399 exampleVal()
400 example1()
401 example2()
402 example3()
403 example4()
404