tqdm在Jupyter笔记本重复打印新的进度条

我正在使用tqdm来打印我在Jupyter笔记本上运行的脚本中的进度。我正在通过tqdm.write()将所有消息打印到控制台。然而,这仍然给我一个倾斜的输出,如下所示:

enter image description here

也就是说,每当需要打印新的一行时,下一行就会打印一个新的进度条。当我通过终端运行脚本时,这不会发生。我怎么解决这个问题?

243865 次浏览

尝试使用tqdm.notebook.tqdm而不是tqdm,如概述的在这里

这可以像更改您的导入一样简单:

from tqdm.notebook import tqdm

好运!

经过测试,似乎tqdm实际上在Jupyter笔记本的“文本模式”中工作良好。这很难判断,因为你没有提供最小的例子,但看起来你的问题是由每次迭代中的print语句引起的。print语句在每次状态栏更新之间输出一个数字(~0.89),这使输出变得混乱。尝试删除打印语句。

这是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:

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]

在这里,我们可以看到木星似乎直到这条线的尽头才被清除。我们可以通过添加空格来添加另一种解决方法。如:

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适用于你,就使用它(但这样你可能读不到那么远)。

如果这里的其他技巧不起作用,并且-就像我一样-你通过progress_apply使用pandas集成,你可以让tqdm处理它:

from tqdm.autonotebook import tqdm
tqdm.pandas()


df.progress_apply(row_function, axis=1)

这里的要点在于tqdm.autonotebook模块。正如IPython笔记本的使用说明中所述,这使得tqdm在Jupyter笔记本和Jupyter控制台中使用的进度条格式之间进行选择-由于我还没有进一步调查的原因,tqdm.autonotebook选择的特定格式在pandas中工作顺利,而所有其他格式都不能,特别是progress_apply

为了完成oscarbranson的回答:根据进度条的运行位置,可以自动选择控制台或笔记本版本的进度条:

from tqdm.autonotebook import tqdm

更多信息可以找到在这里

以上这些对我都没用。我发现在错误后运行以下程序对这个问题进行排序(它只是在后台清除进度条的所有实例):

from tqdm import tqdm


# blah blah your code errored


tqdm._instances.clear()

大多数答案现在都过时了。如果正确导入tqdm会更好。

from tqdm import tqdm_notebook as tqdm

enter image description here

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

对于每个人谁是在窗口,不能解决复制条的问题与任何解决方案在这里提到。我必须安装colorama包,如Tqdm的已知问题所述,它修复了它。

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]

进度条使用tqdm的另一个例子

      from tqdm import tqdm
my_list = list(range(100))
with tqdm(total=len(my_list)) as pbar:
for x in my_list:
pbar.update(1)

在我的情况下,我只需要更新ipywidgets,以摆脱使用常规from tqdm import tqdm时的额外打印。

使用Python 3.9.2tqdm==4.62.3:

from tqdm.notebook import tqdm


for item in tqdm(list_of_items):
do_something(item)

tqdm自动加载合适的进度条,无论是普通代码或交互环境通过

from tqdm.auto import tqdm