@@ -72,13 +72,19 @@ The progressbar module is very easy to use, yet very powerful. It will also
72
72
automatically enable features like auto-resizing when the system supports it.
73
73
74
74
******************************************************************************
75
- Known issues
75
+ Security contact information
76
76
******************************************************************************
77
77
78
- Due to limitations in both the IDLE shell and the Jetbrains (Pycharm) shells this progressbar cannot function properly within those.
78
+ To report a security vulnerability, please use the
79
+ `Tidelift security contact <https://tidelift.com/security >`_.
80
+ Tidelift will coordinate the fix and disclosure.
81
+
82
+ ******************************************************************************
83
+ Known issues
84
+ ******************************************************************************
79
85
86
+ - The Jetbrains (PyCharm, etc) editors work out of the box, but for more advanced features such as the `MultiBar ` support you will need to enable the "Enable terminal in output console" checkbox in the Run dialog.
80
87
- The IDLE editor doesn't support these types of progress bars at all: https://bugs.python.org/issue23220
81
- - The Jetbrains (Pycharm) editors partially work but break with fast output. As a workaround make sure you only write to either `sys.stdout ` (regular print) or `sys.stderr ` at the same time. If you do plan to use both, make sure you wait about ~200 milliseconds for the next output or it will break regularly. Linked issue: https://github.com/WoLpH/python-progressbar/issues/115
82
88
- Jupyter notebooks buffer `sys.stdout ` which can cause mixed output. This issue can be resolved easily using: `import sys; sys.stdout.flush() `. Linked issue: https://github.com/WoLpH/python-progressbar/issues/173
83
89
84
90
******************************************************************************
@@ -152,6 +158,38 @@ In most cases the following will work as well, as long as you initialize the
152
158
logging.error(' Got %d ' , i)
153
159
time.sleep(0.2 )
154
160
161
+ Multiple (threaded) progressbars
162
+ ==============================================================================
163
+
164
+ .. code :: python
165
+
166
+ import random
167
+ import threading
168
+ import time
169
+
170
+ import progressbar
171
+
172
+ BARS = 5
173
+ N = 50
174
+
175
+
176
+ def do_something (bar ):
177
+ for i in bar(range (N)):
178
+ # Sleep up to 0.1 seconds
179
+ time.sleep(random.random() * 0.1 )
180
+
181
+ # print messages at random intervals to show how extra output works
182
+ if random.random() > 0.9 :
183
+ bar.print(' random message for bar' , bar, i)
184
+
185
+
186
+ with progressbar.MultiBar() as multibar:
187
+ for i in range (BARS ):
188
+ # Get a progressbar
189
+ bar = multibar[f ' Thread label here { i} ' ]
190
+ # Create a thread and pass the progressbar
191
+ threading.Thread(target = do_something, args = (bar,)).start()
192
+
155
193
Context wrapper
156
194
==============================================================================
157
195
.. code :: python
@@ -238,55 +276,72 @@ Bar with wide Chinese (or other multibyte) characters
238
276
for i in bar(range (10 )):
239
277
time.sleep(0.1 )
240
278
241
- Showing multiple (threaded) independent progress bars in parallel
279
+ Showing multiple independent progress bars in parallel
242
280
==============================================================================
243
281
244
- While this method works fine and will continue to work fine, a smarter and
245
- fully automatic version of this is currently being made:
246
- https://github.com/WoLpH/python-progressbar/issues/176
247
-
248
282
.. code :: python
249
283
250
284
import random
251
285
import sys
252
- import threading
253
286
import time
254
287
255
288
import progressbar
256
289
257
- output_lock = threading.Lock()
290
+ BARS = 5
291
+ N = 100
292
+
293
+ # Construct the list of progress bars with the `line_offset` so they draw
294
+ # below each other
295
+ bars = []
296
+ for i in range (BARS ):
297
+ bars.append(
298
+ progressbar.ProgressBar(
299
+ max_value = N,
300
+ # We add 1 to the line offset to account for the `print_fd`
301
+ line_offset = i + 1 ,
302
+ max_error = False ,
303
+ )
304
+ )
258
305
306
+ # Create a file descriptor for regular printing as well
307
+ print_fd = progressbar.LineOffsetStreamWrapper(sys.stdout, 0 )
259
308
260
- class LineOffsetStreamWrapper :
261
- UP = ' \033 [F '
262
- DOWN = ' \033 [B '
309
+ # The progress bar updates, normally you would do something useful here
310
+ for i in range (N * BARS ):
311
+ time.sleep( 0.005 )
263
312
264
- def __init__ (self , lines = 0 , stream = sys.stderr):
265
- self .stream = stream
266
- self .lines = lines
313
+ # Increment one of the progress bars at random
314
+ bars[random.randrange(0 , BARS )].increment()
267
315
268
- def write (self , data ):
269
- with output_lock:
270
- self .stream.write(self .UP * self .lines)
271
- self .stream.write(data)
272
- self .stream.write(self .DOWN * self .lines)
273
- self .stream.flush()
316
+ # Print a status message to the `print_fd` below the progress bars
317
+ print (f ' Hi, we are at update { i+ 1 } of { N * BARS } ' , file = print_fd)
274
318
275
- def __getattr__ (self , name ):
276
- return getattr (self .stream, name)
319
+ # Cleanup the bars
320
+ for bar in bars:
321
+ bar.finish()
277
322
323
+ # Add a newline to make sure the next print starts on a new line
324
+ print ()
278
325
279
- bars = []
280
- for i in range (5 ):
281
- bars.append(
282
- progressbar.ProgressBar(
283
- fd = LineOffsetStreamWrapper(i),
284
- max_value = 1000 ,
285
- )
286
- )
326
+ ******************************************************************************
287
327
288
- if i:
289
- print (' Reserve a line for the progressbar' )
328
+ Naturally we can do this from separate threads as well:
329
+
330
+ .. code :: python
331
+
332
+ import random
333
+ import threading
334
+ import time
335
+
336
+ import progressbar
337
+
338
+ BARS = 5
339
+ N = 100
340
+
341
+ # Create the bars with the given line offset
342
+ bars = []
343
+ for line_offset in range (BARS ):
344
+ bars.append(progressbar.ProgressBar(line_offset = line_offset, max_value = N))
290
345
291
346
292
347
class Worker (threading .Thread ):
@@ -295,10 +350,12 @@ https://github.com/WoLpH/python-progressbar/issues/176
295
350
self .bar = bar
296
351
297
352
def run (self ):
298
- for i in range (1000 ):
299
- time.sleep(random.random() / 100 )
353
+ for i in range (N ):
354
+ time.sleep(random.random() / 25 )
300
355
self .bar.update(i)
301
356
302
357
303
358
for bar in bars:
304
359
Worker(bar).start()
360
+
361
+ print ()
0 commit comments