175

I am using tqdm to print progress in a script I'm running in a Jupyter notebook. I am printing all messages to the console via tqdm.write(). However, this still gives me a skewed output like so:

enter image description here

That is, each time a new line has to be printed, a new progress bar is printed on the next line. This does not happen when I run the script via terminal. How can I solve this?

Community
  • 1
  • 1
Rohan Saxena
  • 2,465
  • 2
  • 10
  • 32

8 Answers8

267

Try using tqdm.notebook.tqdm instead of tqdm, as outlined here.

This could be as simple as changing your import to:

from tqdm.notebook import tqdm

Good luck!

EDIT: After testing, it seems that tqdm actually works fine in 'text mode' in Jupyter notebook. It's hard to tell because you haven't provided a minimal example, but it looks like your problem is caused by a print statement in each iteration. The print statement is outputting a number (~0.89) in between each status bar update, which is messing up the output. Try removing the print statement.

fdermishin
  • 3,167
  • 3
  • 19
  • 42
oscarbranson
  • 2,939
  • 1
  • 10
  • 14
  • 2
    I haven't used a `print()` statement, I used `tqdm.write()`. However, `tqdm_notebook` gives good results. Thanks : ) – Rohan Saxena Feb 14 '17 at 09:00
  • Do you know if it supports Python 3.6? I've not had luck with this – Jon Oct 08 '17 at 17:59
  • 1
    What error are you getting? It works fine for me. Impossible to help with so little info... Have you [enabled ipywidgets in jupyer](http://ipywidgets.readthedocs.io/en/stable/user_install.html)? Have you just plain `tqdm`, rather than `tqdm_notebook`? This works well with Python 3.6 and Jupyter 1.0.0. – oscarbranson Oct 10 '17 at 03:11
  • tqdm_notebook from tqdm 4.19.4 is working for me on Python 3.6, Jupyter notebook 5.0.0, and ipywidgets 7.0.3. – Matt Kleinsmith Oct 31 '17 at 21:50
  • has anyone gotten `tqdm.tqdm.pandas()` to work with `tqdm.tqdm_notebook`? I'd like to use both. – François Leblanc Oct 17 '18 at 15:04
  • I am not sure if it really helps, but I just faced the same issue - with a for loop. I tried tqdm_notebook but its not giving the progressbar (I am in Python 3.6). On re-trying with tqdm itself however, it worked again. So though I don't know the reason, just retrying with tqdm has helped me. – Dileep Kumar Patchigolla Dec 03 '18 at 05:38
  • @justacluelessnewbie you broke the import – bugmenot123 Jan 14 '20 at 11:03
  • 2
    @bugmenot123 Good catch, fixed. – Czyzby Jan 15 '20 at 09:12
  • actually made it worse for me.. now there are 2 newlines after each iteration rather than one... – TheSneak May 06 '20 at 05:08
  • 1
    This seems to be an easiest way: `from tqdm.autonotebook import tqdm` – Iopheam Nov 03 '20 at 15:43
  • This works for me in Windows, but in Linux it doesn't show progress bar (just a weird text like Hbox...) – igorkf Feb 12 '21 at 16:01
46

This is an alternative answer for the case where tqdm_notebook doesn't work for you.

Given the following example:

from time import sleep
from tqdm import tqdm

values = range(3)
with tqdm(total=len(values)) as pbar:
    for i in values:
        pbar.write('processed: %d' %i)
        pbar.update(1)
        sleep(1)

The output would look something like this (progress would show up red):

  0%|          | 0/3 [00:00<?, ?it/s]
processed: 1
 67%|██████▋   | 2/3 [00:01<00:00,  1.99it/s]
processed: 2
100%|██████████| 3/3 [00:02<00:00,  1.53it/s]
processed: 3

The problem is that the output to stdout and stderr are processed asynchronously and separately in terms of new lines.

If say Jupyter receives on stderr the first line and then the "processed" output on stdout. Then once it receives an output on stderr to update the progress, it wouldn't go back and update the first line as it would only update the last line. Instead it will have to write a new line.

Workaround 1, writing to stdout

One workaround would be to output both to stdout instead:

import sys
from time import sleep
from tqdm import tqdm

values = range(3)
with tqdm(total=len(values), file=sys.stdout) as pbar:
    for i in values:
        pbar.write('processed: %d' % (1 + i))
        pbar.update(1)
        sleep(1)

The output will change to (no more red):

processed: 1   | 0/3 [00:00<?, ?it/s]
processed: 2   | 0/3 [00:00<?, ?it/s]
processed: 3   | 2/3 [00:01<00:00,  1.99it/s]
100%|██████████| 3/3 [00:02<00:00,  1.53it/s]

Here we can see that Jupyter doesn't seem to clear until the end of the line. We could add another workaround for that by adding spaces. Such as:

import sys
from time import sleep
from tqdm import tqdm

values = range(3)
with tqdm(total=len(values), file=sys.stdout) as pbar:
    for i in values:
        pbar.write('processed: %d%s' % (1 + i, ' ' * 50))
        pbar.update(1)
        sleep(1)

Which gives us:

processed: 1                                                  
processed: 2                                                  
processed: 3                                                  
100%|██████████| 3/3 [00:02<00:00,  1.53it/s]

Workaround 2, set description instead

It might in general be more straight forward not to have two outputs but update the description instead, e.g.:

import sys
from time import sleep
from tqdm import tqdm

values = range(3)
with tqdm(total=len(values), file=sys.stdout) as pbar:
    for i in values:
        pbar.set_description('processed: %d' % (1 + i))
        pbar.update(1)
        sleep(1)

With the output (description updated while it's processing):

processed: 3: 100%|██████████| 3/3 [00:02<00:00,  1.53it/s]

Conclusion

You can mostly get it to work fine with plain tqdm. But if tqdm_notebook works for you, just use that (but then you'd probably not read that far).

de1
  • 2,488
  • 9
  • 25
28

Most of the answers are outdated now. Better if you import tqdm correctly.

from tqdm import tqdm_notebook as tqdm

enter image description here

Willie Cheng
  • 5,589
  • 7
  • 39
  • 58
  • 14
    It changed again: `TqdmDeprecationWarning: This function will be removed in tqdm==5.0.0 Please use tqdm.notebook.tqdm instead of tqdm.tqdm_notebook` – stason Mar 05 '20 at 04:00
15

If the other tips here don't work and - just like me - you're using the pandas integration through progress_apply, you can let tqdm handle it:

from tqdm.autonotebook import tqdm
tqdm.pandas()

df.progress_apply(row_function, axis=1)

The main point here lies in the tqdm.autonotebook module. As stated in their instructions for use in IPython Notebooks, this makes tqdm choose between progress bar formats used in Jupyter notebooks and Jupyter consoles - for a reason still lacking further investigations on my side, the specific format chosen by tqdm.autonotebook works smoothly in pandas, while all others didn't, for progress_apply specifically.

Julio Cezar Silva
  • 1,332
  • 1
  • 11
  • 24
13

None of the above works for me. I find that running the following sorts this issue after error (It just clears all the instances of progress bars in the background):

from tqdm import tqdm

# blah blah your code errored

tqdm._instances.clear()
James Owers
  • 6,707
  • 8
  • 47
  • 60
  • 1
    Thank you! However it throws and error if no instances exists. Still want to use it with scripts and Hydrogen IDE. Here is my code. `try: # Avoids problem on notebooks / Hydrogen IDE tqdm.tqdm._instances.clear() except Exception: pass` – Jacques Peeters Mar 22 '20 at 21:19
  • Yup it will throw an exception if no instance exists. Is there an issue with your try except approach? – James Owers Mar 29 '20 at 13:26
  • 1
    This is exactly what I was looking for. I will be adding this line regularly in my notebooks from now on. Thanks @JamesOwers – DrRDN Dec 31 '20 at 20:35
12

To complete oscarbranson's answer: it's possible to automatically pick console or notebook versions of progress bar depending on where it's being run from:

from tqdm.autonotebook import tqdm

More info can be found here

mjarosie
  • 1,290
  • 15
  • 25
4

For everyone who is on windows and couldn't solve the duplicating bars issue with any of the solutions mentioned here. I had to install the colorama package as stated in tqdm's known issues which fixed it.

pip install colorama

Try it with this example:

from tqdm import tqdm
from time import sleep

for _ in tqdm(range(5), "All", ncols = 80, position = 0):
    for _ in tqdm(range(100), "Sub", ncols = 80, position = 1, leave = False):
        sleep(0.01)

Which will produce something like:

All:  60%|████████████████████████                | 3/5 [00:03<00:02,  1.02s/it]
Sub:  50%|██████████████████▌                  | 50/100 [00:00<00:00, 97.88it/s]
Nebulo
  • 121
  • 6
-1

Use tqdm_notebook

from tqdm import tqdm_notebook as tqdm

x=[1,2,3,4,5]

for i in tqdm(range(0,len(x))):

    print(x[i])
Kranthi
  • 204
  • 2
  • 2