Is there a way to have multiple concurrent and independent progress bars?
Description
I have 2 concurrent processes (threads really) performing operations that are independent. I would like to have 2 progress bars (as 2 lines) to show the progress of each. The first one is bound (number of tasks known), the second one is not (number of tasks unknown)
Is that possible? I didn't see anything obvious in the examples
There's a simpler version available called the multi-bar: https://github.com/WoLpH/python-progressbar/pull/208
But the full feature is still a work in progress: https://github.com/WoLpH/python-progressbar/issues/189
Yes, I'm aware of the multi-bar (I already use it for something else), but here the 2 processes are (almost) completely independent and of different nature, so the multi-bar wouldn't work.
Any idea when you think the full feature might become available?
Well... I've been thinking about the feature for a few years now with little time to work on it. But I've probably been thinking of a much too difficult solution for the issue :)
I've got a workaround that isn't full support, but I think it works rather well :)
import sys
import time
import progressbar
class LineOffsetStreamWrapper:
UP = '\033[F'
DOWN = '\033[B'
def __init__(self, lines=0, stream=sys.stderr):
self.stream = stream
self.lines = lines
def write(self, data):
self.stream.write(self.UP * self.lines)
self.stream.write(data)
self.stream.write(self.DOWN * self.lines)
self.stream.flush()
def __getattr__(self, name):
return getattr(self.stream, name)
bars = []
for i in range(5):
bars.append(progressbar.ProgressBar(
fd=LineOffsetStreamWrapper(i),
max_value=1000,
))
if i:
print('Reserve a line for the progressbar')
for i in range(100):
for j, bar in enumerate(bars, 1):
bar.update(i * j)
time.sleep(0.1)
Would this work for you? :)
I will test this and get back to you.
I've properly added the feature now. I'm still testing with it but I believe it works quite well. Usage: https://github.com/wolph/python-progressbar#multiple-threaded-progressbars
import random
import threading
import time
import progressbar
BARS = 5
N = 50
def do_something(bar):
for i in bar(range(N)):
# Sleep up to 0.1 seconds
time.sleep(random.random() * 0.1)
# print messages at random intervals to show how extra output works
if random.random() > 0.9:
bar.print('random message for bar', bar, i)
with progressbar.MultiBar() as multibar:
for i in range(BARS):
# Get a progressbar
bar = multibar[f'Thread label here {i}']
# Create a thread and pass the progressbar
threading.Thread(target=do_something, args=(bar,)).start()
You can add your custom progressbars to a MultiBar instance like this:
multi['Some label'] = your_progress
Thanks. I'm afraid I've now changed job, and the project I was planning on using that on is now dead...
Hopefully I get to make use of it in the near future in a new project
No worries :)
If you ever need it in the future you know where to find it ;)