Double Progress Bar in Python Double Progress Bar in Python python python

Double Progress Bar in Python


Use the nested progress bars feature of tqdm, an extremely low overhead, very customisable progress bar library:

$ pip install -U tqdm

Then:

from tqdm import tqdm# from tqdm.auto import tqdm  # notebook compatibleimport timefor i1 in tqdm(range(5)):    for i2 in tqdm(range(300), leave=False):        # do something, e.g. sleep        time.sleep(0.01)

(The leave=False is optional - needed to discard the nested bars upon completion.)

You can also use from tqdm import trange and then replace tqdm(range(...)) with trange(...). You can also get it working in a notebook.


I basically just want to add to the answer of @casper.dcl. In the slightly different case, where you have two nested for loops and want just a SINGLE progress bar you can do the following.

from tqdm import tqdmimport timen = 5m = 300with tqdm(total=n * m) as pbar:    for i1 in tqdm(range(n)):        for i2 in tqdm(range(m)):            # do something, e.g. sleep            time.sleep(0.01)            pbar.update(1)

I know that was not the question, but it might be still helpful for some folks.


It would require you to move the cursor position. I have written you a hacky thing to do it.

This script relies on the fact that the progressbar module assumes that you are on a fresh line to draw the progress bar. By simply moving the cursor up (using the escape code for "move cursor 1 row up"), and down (just using a newline. I could also use an escape code, but newline is easier and faster), one can maintain multiple progress bars.

import progressbar, time, sysdef up():    # My terminal breaks if we don't flush after the escape-code    sys.stdout.write('\x1b[1A')    sys.stdout.flush()def down():    # I could use '\x1b[1B' here, but newline is faster and easier    sys.stdout.write('\n')    sys.stdout.flush()# Total bar is at the bottom. Move down to draw itdown()total = progressbar.ProgressBar(maxval=50)total.start()for i in range(1,51):    # Move back up to prepare for sub-bar    up()    # I make a new sub-bar for every iteration, thinking it could be things    # like "File progress", with total being total file progress.    sub = progressbar.ProgressBar(maxval=50)    sub.start()    for y in range(51):        sub.update(y)        time.sleep(0.005)    sub.finish()    # Update total - The sub-bar printed a newline on finish, so we already    # have focus on it    total.update(i)total.finish()

This is of course a bit hacky, but it gets the job done. I hope that it is useful.