Feature: multilevel progressbar
It would be great to be able to wrap several nested iterables like
for i in progressbar.progressbar(range(20)):
for j in progressbar.progressbar(range(5)):
time.sleep(0.1)
As for now this results in multiple progress bars appearing one after another. It could look like this instead
20% (1 of 5) |##### | Elapsed Time: 0:00:02 ETA: 0:00:03
30% (6 of 20) |##### | Elapsed Time: 0:01:02 ETA: 0:06:01
Also, it looks like this could be a possible step on the way to that one https://github.com/WoLpH/python-progressbar/issues/176
It's indeed very similar to #176 and I'm guessing the solution will be the same. Although the threading versions might take slightly more effort.
It's been on my to-do list for a while but it's going to be a bit of work to do it right.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Not quite the same, but I implemented a multi-bar: #208
@paulo-raca it looks like something that solves it and even looks gorgeous. Thanks for your work!
@WoLpH I'm happy with #208.
Feel free to close this one if it looks redundant to you now.
I love the multibar hack but I still think there is a need for a good multi progressbar solution. There are several limitations to this implementation which makes it hard/impractical to use in some cases.
That doesn't make this any less useful, it could be an addition to this feature. Once the multiple progressbars are working this one could be the "global" progressbar between them :)
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
As a reasonable workaround, I've wrote this little bit of script:
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)
It's certainly not as foolproof and well-tested as the rest of the progressbar code, but I think it should do the trick for the common use-cases :)
I've properly added the feature of multiple progressbars now.
The approach is a bit different from tqdm but I personally think this is a more obvious (although slightly more verbose) approach.
The MultiBar can be used both using a with MultiBar() as multibar: and using a regular instance. You can manually render on demand using multibar.render() if you already have a display loop. If you want to have it render in the background you can use multibar.start() to run it as a background thread.
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
The new version with this feature has been released :)
You did not add an example in the examples.py file from what I can see. Would be nice to have one!
The issue is that the threaded example, opposed to all other examples, doesn't work in all environments so I'm not a 100% sure where I should enable/disable it. But I'll add it to the examples at least for where I can detect an ANSI terminal :)