@@ -72,13 +72,19 @@ The progressbar module is very easy to use, yet very powerful. It will also
7272automatically enable features like auto-resizing when the system supports it.
7373
7474******************************************************************************
75- Known issues
75+ Security contact information
7676******************************************************************************
7777
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+ ******************************************************************************
7985
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.
8087- 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
8288- 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
8389
8490******************************************************************************
@@ -152,6 +158,38 @@ In most cases the following will work as well, as long as you initialize the
152158 logging.error(' Got %d ' , i)
153159 time.sleep(0.2 )
154160
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+
155193 Context wrapper
156194==============================================================================
157195.. code :: python
@@ -238,55 +276,72 @@ Bar with wide Chinese (or other multibyte) characters
238276 for i in bar(range (10 )):
239277 time.sleep(0.1 )
240278
241- Showing multiple (threaded) independent progress bars in parallel
279+ Showing multiple independent progress bars in parallel
242280==============================================================================
243281
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-
248282.. code :: python
249283
250284 import random
251285 import sys
252- import threading
253286 import time
254287
255288 import progressbar
256289
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+ )
258305
306+ # Create a file descriptor for regular printing as well
307+ print_fd = progressbar.LineOffsetStreamWrapper(sys.stdout, 0 )
259308
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 )
263312
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()
267315
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)
274318
275- def __getattr__ (self , name ):
276- return getattr (self .stream, name)
319+ # Cleanup the bars
320+ for bar in bars:
321+ bar.finish()
277322
323+ # Add a newline to make sure the next print starts on a new line
324+ print ()
278325
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+ ******************************************************************************
287327
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))
290345
291346
292347 class Worker (threading .Thread ):
@@ -295,10 +350,12 @@ https://github.com/WoLpH/python-progressbar/issues/176
295350 self .bar = bar
296351
297352 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 )
300355 self .bar.update(i)
301356
302357
303358 for bar in bars:
304359 Worker(bar).start()
360+
361+ print ()
0 commit comments