Dror Hilman
Dror Hilman

Reputation: 7447

Can I add message to the tqdm progressbar?

When using the tqdm progress bar: can I add a message to the same line as the progress bar in a loop?

I tried using the "tqdm.write" option, but it adds a new line on every write. I would like each iteration to show a short message next to the bar, that will disappear in the next iteration. Is this possible?

Upvotes: 263

Views: 277245

Answers (8)

Ghrua
Ghrua

Reputation: 7656

The example shown in Usage of tqdm works well for me.

pbar = tqdm(["a", "b", "c", "d"])
for char in pbar:
    pbar.set_description("Processing %s" % char)

Or alternatively, starting Python 3.8 which supports the walrus operator :=:

for char in (pbar := tqdm(["a", "b", "c", "d"])):
    pbar.set_description(f"Processing {char}")

Upvotes: 489

MbBrainz
MbBrainz

Reputation: 130

When using the tqdm progress bar in Python, there are different ways to define it, either by using the with statement or by assigning the progress bar to a variable with tqdm() function. In some cases, you may want to update the progress bar inside the loop without adding an extra indentation layer.

To achieve this, you can use the set_postfix() method to update the progress bar with the latest information. To avoid adding an extra indentation layer, you can define the progress bar outside of the loop and use it inside the loop. For example, you can use the enumerate() function to iterate over a list while keeping track of the index, and then pass this to the progress bar like this:

from tqdm import tqdm

object_list = ["a", "b", "c"]

pbar = tqdm(enumerate(object_list), descr="...")
for i, obj in pbar:
    ...
    pbar.set_postfix("foo")
    ...
    pbar.set_postfix("bar")

In this way, you define the tqdm progress bar before the loop, and then you can use the set_postfix() method to update the progress bar inside the loop without adding an extra indentation layer. By using the enumerate() function, you also have access to the current index, which you can pass to the set_postfix() method to display it in the progress bar.

This approach provides the flexibility to update the progress bar inside the loop while keeping the code clean and readable. This answer is based on the comments from @cbrnr and @tim-mb.

Upvotes: -1

learner
learner

Reputation: 3472

Although all the answers here are correct, tqdm also provides a set_postfix_str method. The advantage over set_postfix is that you can pass your own formatted string in place of key value pairs. Also set_postfix sorts the key value pairs alphabetically. Here is an MWE.

from tqdm import tqdm
import numpy as np

loop_obj = tqdm(np.arange(10))

for i in loop_obj:
    loop_obj.set_description(f"Count: {i}")  # Adds text before progessbar
    loop_obj.set_postfix_str(f"Next count: {i+1}")  # Adds text after progressbar

Upvotes: 9

Claude COULOMBE
Claude COULOMBE

Reputation: 3738

I personally use .set_description() and a progression_bar assignment statement before the for loop:

from tqdm import tqdm

progression_bar = tqdm(["An", "iterable", "object"])
for element in (progression_bar):
    progression_bar.set_description("Processing « %s »" % str(element))

Upvotes: 3

Bhanuka Manesha
Bhanuka Manesha

Reputation: 1797

Other answers focus on dynamic description, but for a static description you can add a desc argument into the tqdm function.

from tqdm import tqdm

x = [5]*1000
for _ in tqdm(x, desc="Example"):
    pass
 
Example: 100%|██████████████████████████████████| 1000/1000 [00:00<00:00, 1838800.53it/s]

Upvotes: 165

Matt Raymond
Matt Raymond

Reputation: 101

I personally find it much cleaner to use the with statement:

from tqdm import tqdm

with tqdm(['a','b','c']) as t:
  for c in t:
    t.set_description(f'{c}')

Upvotes: 9

gaborous
gaborous

Reputation: 16570

You can change the description to show a small message before the progress bar, like this:

from tqdm import trange
from time import sleep
t = trange(100, desc='Bar desc', leave=True)
for i in t:
    t.set_description("Bar desc (file %i)" % i)
    t.refresh() # to show immediately the update
    sleep(0.01)

/EDIT: in the latest releases of tqdm, you can use t.set_description("text", refresh=True) (which is the default) and remove t.refresh() (thanks to Daniel for the tip).

Upvotes: 163

Markus
Markus

Reputation: 1965

You can use set_postfix to add values directly to the bar.

Example:

from tqdm import tqdm
pbar = tqdm(["a", "b", "c", "d"])
num_vowels = 0
for ichar in pbar:
    if ichar in ['a','e','i','o','u']:
        num_vowels += 1
    pbar.set_postfix({'num_vowels': num_vowels})

The postfix dictionary is integrated into the progress bar:

100%|███████████| 4/4 [00:11<00:00,  2.93s/it, num_vowels=1]

Instead of a dictionary, you can use set_postfix_str to just add a string to the end of the progress bar.

Upvotes: 110

Related Questions