How to use nested progress bars with tqdm in Python

Categories

In this post, I will show you how to use nested progress bars with tqdm in Python, a popular library for displaying progress information in loops. This can be useful when you have a loop inside another loop, and you want to monitor the progress of both loops.

The problem

Suppose you have a code like this:

from tqdm import tqdm
import time

for a in tqdm(range(1,7), desc="outer loop"):
    for b in tqdm(range(1,12), desc="inner loop"):
        time.sleep(0.01)

This code uses two tqdm instances, one for the outer loop and one for the inner loop. The desc argument sets the description for each progress bar. The function() is a placeholder for some computation that you want to perform in each iteration. The time.sleep(0.01) is just to simulate some delay.

If you run this code in a terminal, you will see something like this:

outer loop:  17%|█▋        | 1/6 [00:01<00:05,  1.20s/it]
inner loop: 100%|██████████| 11/11 [00:00<00:00, 98.76it/s]

The problem is that the inner loop’s progress bar is printed on a new line every time it finishes, creating a lot of clutter in the output. This makes it hard to see the progress of the outer loop.

The solution

To fix this issue, you need to do two things:

  • Enable the option “Emulate terminal in output console” in your PyCharm run/debug configuration.
  • Set the leave argument to False for the inner loop’s tqdm instance.

The leave argument controls whether the progress bar should remain in the output after it finishes. By setting it to False, the inner loop’s progress bar will be cleared from the output when it completes, leaving only the outer loop’s progress bar.

Your code should look something like this:

from tqdm import tqdm
import time

for a in tqdm(range(1,7), desc="outer loop"):
    for b in tqdm(range(1,12), desc="inner loop", leave=False):
        function()
        time.sleep(0.01)

Now, if you run this code in a terminal, you will see something like this:

outer loop:  17%|█▋        | 1/6 [00:01<00:05,  1.20s/it]
inner loop: 100%|██████████| 11/11 [00:00<00:00, 98.76it/s]

Notice how the inner loop’s progress bar is updated in the same line, and does not create any extra lines in the output. This makes it easier to see the progress of the outer loop.

A note on Jupyter notebooks

If you are using Jupyter notebooks, you may need to use a different version of tqdm for displaying progress bars in notebooks . You can try to import tqdm from tqdm.notebook or tqdm.auto instead of tqdm . This should make the nested progress bars display correctly in your notebook.

Alternatively, you can use a single progress bar to monitor the total iterations of both loops, as shown in this example:

from tqdm.contrib import itertools
import time
for i1, i2 in itertools.product(range(5), range(300)):
    # do something, e.g. sleep
    time.sleep(0.01)

Conclusion

In this post, I showed you how to use nested progress bars with tqdm in Python, and how to fix the issue of the inner loop’s progress bar printing on a new line every time it finishes. I hope you found this post useful and learned something new. If you have any questions or feedback, feel free to leave a comment below. 😊

: https://www.jetbrains.com/help/pycharm/run-debug-configuration-python.html#emulate-terminal : https://github.com/tqdm/tqdm#nested-progress-bars : https://stackoverflow.com/questions/42212810/tqdm-in-jupyter-notebook : https://tqdm.github.io/docs/notebook/