-
-
Notifications
You must be signed in to change notification settings - Fork 208
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Displaying multiple bars at once #20
Comments
Hey @blueberryberet, thank you for your kind words, I'm glad you liked it! Unfortunately, it's not simple to support multithreading. The error you reported could be easily fixed, but I think the results would be unpredictable. My Would you have some test code? |
As I'm sure you've seen, it is fixed in 1.3.3, but we're in unpredictable territory now. |
Hi @rsalmei, using 1.3.3 did indeed fix my error and many thanks for that. I've simplified my code below. The output is of both bars being drawn at the same cursor position, alternating between the two. I've tried several methods to try to draw them in different positions. One method was to call sys.stdout.write('\n') and sys.stdout.write('\x1b[1A') in between when each thread calls bar(). I also tried setting a global variable that would alternate between 0 and 1 each time each thread calls bar() to avoid any timing delays between threads. I also tried multiprocessing and calling alive_bar as a subprocess. I note that increasing time.sleep() does not reduce the rate at which the bars are alternating between each other so maybe they are not refreshed/redrawn each time bar() is called? Maybe using curses library might give an answer. Despite your well documented code, I'm struggling to understand how the bars are `drawn. import time
import sys
import threading
from alive_progress import alive_bar
def up():
sys.stdout.write('\x1b[1A')
sys.stdout.flush()
def down():
sys.stdout.write('\n')
sys.stdout.flush()
def task_1():
global value
items = range(1000)
with alive_bar(len(items)) as bar:
for item in items:
while True:
if value == 0:
down()
bar()
time.sleep(0.5)
value = 1
def task_2():
global value
items = range(2000)
with alive_bar(len(items)) as bar:
for item in items:
while True:
if value == 1:
up()
bar()
time.sleep(0.5)
value = 0
t1 = threading.Thread(target=task1)
t2 = threading.Thread(target=task2)
t1.start()
t2.start() |
I was able to use escape codes to move the cursor as each bar was being drawn to solve the problem. I know this is a very hacky way of doing this but it works for my purposes! Thanks for your help and code!
|
@blueberryberet |
Sure, no problem. It's been a while since I've looked at this and have never been good at commenting. I'll try to give a more detailed description when I have more time or let me know if you have a specific question, but here's the code. When you run alive-progress in multiple threads it will try to render each bar on top of each other. I essentially added a move function to the progress.py module in rsalmei's code that redraws the cursor to a different row in the console each time alive_bar is called. I also passed two new arguments to progress.py, position and torrent_name. Above where update_data() is called in alive_repr function, I call the move function to draw the divider, torrent_name and bar at the various correct rows.
This is a simplified version of my own python script that connects to qbittorrent and calls the alive-progress module using multithreading. Let me know if you want the full code. I'm not sure if your also using this to display torrent info or have a different idea. I'm also using the new windows terminal, you can get rid of the flashing cursor by editing the profiles.json file and setting the colour the same as your background
def task(torrent, x): torrent_list = [ |
Hello @blueberryberet, thanks for your ideias. Also, if I were to implement that, I would have two more concerns:
What do you think? Any considerations?? |
Oh, forgot to say, in your GIF, it seems all the bars ended up leveling to the same speed, which would confirm my concern 1, that it is not easy to refresh at seemingly different speeds. Is it really the case? |
Hello @blueberryberet and @rsalmei , First, congratulations for provide to us this powerfull tool and tips. My case is a bit different, your implementation "work" for me. A doubt, is it possible to start the bars at the end/under of the last line printed/utilized of the terminal regardless of anything? because I provide some information (print) before starting the bars and so they are overlapping my prints. My scenario: Terminal begin/first line - Call my script.py My need: Terminal begin/first line - Call my script.py And if i need to expand out the last line, no scrooll appear, new bars its overlapping aggain (i need to show +- 500 simultaneosly progress bars bars) Regards |
@doug1as https://rich.readthedocs.io/en/stable/progress.html#advanced-usage progress_test.mp4test code: import time
from rich.progress import Progress
with Progress() as progress:
print('hello1')
task1 = progress.add_task("[red]Downloading...", total=1000)
task2 = progress.add_task("[green]Processing...", total=1000)
task3 = progress.add_task("[cyan]Cooking...", total=1000)
print('hello2')
i = 0
while not progress.finished:
progress.update(task1, advance=0.5)
progress.update(task2, advance=0.3)
progress.update(task3, advance=0.9)
i+=1
print(f'hello {i}')
time.sleep(0.02) |
I'll try to implement it here. Thanks in advance! |
This is desperately needed, I am trying to run about 15 at once and it just prints them over each other. |
Yeah, I can imagine... |
Hi @rsalmei, I want to run many processes by calling the same function with different param in parallel, and show how many processe have been done like this. from multiprocessing import Pool
import time
def test(p,):
print(p)
time.sleep(3)
if __name__=="__main__":
pool = #Pool(processes=9)
for i in range(7724):
pool.apply_async(test, args=(i,))
print('test')
pool.close()
pool.join() |
Hi @245851712, you are on the wrong thread, you are not trying to display multiple bars at once. Anyway, search the past tickets here for "pool", you'll find several examples of doing what you need. |
Hi! @rsalmei, I think I have a relevant example:
and than I call this function through multiprocessing, like this:
Ideally I want a progressbars both for the inner loops (which are len(tasks) in total and 8 at any given time) |
Thanks for all your hard work, I think this is the best implementation of progress bars in python that I've come across so far. I'm trying to display multiple bars at once to represent independent torrent downloads. I've been able to achieve this using atpbar but when using alive_progress, I get the following error.
Is there a good way to go about doing this? I'm not a developer, just trying this out for fun, so apologies for any glaring misunderstanding on my part.
The text was updated successfully, but these errors were encountered: