问题:Jupyter Notebook中的tqdm反复打印新的进度条

我正在使用tqdm在Jupyter笔记本中运行的脚本打印进度。我正在通过将所有消息打印到控制台tqdm.write()。但是,这仍然给我这样的偏斜输出:

在此处输入图片说明

也就是说,每次必须打印新行时,新进度条都会打印在下一行上。通过终端运行脚本时不会发生这种情况。我该如何解决?

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?


回答 0

尝试使用tqdm.notebook.tqdm,而不是tqdm作为概述这里

这就像将导入更改为:

from tqdm.notebook import tqdm

祝好运!

编辑:经过测试,似乎tqdm在Jupyter笔记本中的“文本模式”下确实可以正常工作。很难说,因为您没有提供最小的示例,但是看来您的问题是由每次迭代中的打印语句引起的。在每个状态栏更新之间,print语句输出一个数字(〜0.89),这使输出混乱。尝试删除打印语句。

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 ouputting a number (~0.89) in between each status bar update, which is messing up the output. Try removing the print statement.


回答 1

对于tqdm_notebook对您不起作用的情况,这是一个替代答案。

给出以下示例:

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)

输出看起来像这样(进度将显示为红色):

  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

问题是stdoutstderr的输出是异步处理的,并根据新行分别进行处理。

如果说Jupyter在stderr上接收第一行,然后在stdout上接收“已处理”输出。然后,一旦它在stderr上收到输出以更新进度,就不会返回并更新第一行,因为它只会更新最后一行。相反,它将不得不写一个新行。

解决方法1,写入stdout

一种解决方法是将两者都输出到stdout:

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)

输出将更改为(不再显示红色):

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]

在这里我们可以看到Jupyter似乎直到行尾才清除。我们可以通过添加空格来添加另一种解决方法。如:

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)

这给了我们:

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

解决方法2,改为设置描述

通常,没有两个输出而是更新描述可能更直接,例如:

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)

输出(处理过程中更新说明):

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

结论

您通常可以使它与纯tqdm一起正常工作。但是,如果tqdm_notebook为您工作,请使用它(但是您可能不会读那么远)。

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).


回答 2

现在大多数答案已经过时了。如果正确导入tqdm,则更好。

from tqdm import tqdm_notebook as tqdm

在此处输入图片说明

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

from tqdm import tqdm_notebook as tqdm

enter image description here


回答 3

如果此处的其他技巧不起作用,并且-和我一样-您正在通过中使用pandas集成progress_apply,则可以进行tqdm处理:

from tqdm.autonotebook import tqdm
tqdm.pandas()

df.progress_apply(row_function, axis=1)

这里的重点在于tqdm.autonotebook模块。正如他们在IPython Notebook中使用的说明中所述,这使得tqdm可以在Jupyter笔记本和Jupyter控制台中使用的进度条格式之间进行选择-由于我这一方面仍缺乏进一步的研究,该特定格式选择的tqdm.autonotebook效果很好pandas,而所有其他格式都没有不是,progress_apply特别是。

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.


回答 4

要完成oscarbranson的答案:可以根据从何处运行进度条来自动选择控制台或笔记本版本的进度条:

from tqdm.autonotebook import tqdm

更多信息可以在这里找到

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


回答 5

以上都不适合我。我发现运行以下命令可以在出现错误后解决此问题(它只会清除后台进度条的所有实例):

from tqdm import tqdm

# blah blah your code errored

tqdm._instances.clear()

None of the above works for me. I find that running to 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()

回答 6

使用tqdm_notebook

从tqdm导入tqdm_notebook作为tqdm

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

对于我在tqdm(len(x))中:

print(x[i])

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])

回答 7

对于在Windows上无法解决此处提到的任何解决方案重复栏问题的每个人。我必须按照修复该问题的tqdm已知问题中的colorama说明安装该软件包。

pip install colorama

通过以下示例进行尝试:

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)

会产生类似:

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

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]

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。