为什么tqdm打印到新一行而不是更新同一行?

149

我正在使用Python编写一个小型命令行游戏,使用tqdm模块显示进度条。我使用msvcrt模块监听用户输入,以中断进度。一旦被中断,用户可以通过在命令行提示符中输入“restart”来重新开始。第二次显示进度条时,不会更新同一行的进度,而是每次创建一个新行。

如何将其显示在同一行上?

Progress bar issue

这段代码片段说明了我对进度条的使用。

def transfer():
    for i in tqdm.tqdm(range(1000), desc="Transfer progress", ncols=100, bar_format='{l_bar}{bar}|'):
        sleep(.1)
        if msvcrt.kbhit():
            if msvcrt.getwche() == ' ':
                interrupt()
                break

def interrupt():
    type("File transfer interrupted, to restart the transfer, type 'restart'")

3
好的,以下是您需要翻译的内容:https://github.com/tqdm/tqdm/issues/375 - sirex
1
https://github.com/tqdm/tqdm/issues/313 - user
3
有没有一个地方可以解释为什么会发生这种情况? - Eduardo Reis
19个回答

168
尝试使用position=0leave=True (在Google Colab中工作的解决方案,以避免换行打印)
from tqdm import tqdm 
import time

def foo_():
    time.sleep(0.3)
range_ = range(0, 10)
total = len(range_)

with tqdm(total=total, position=0, leave=True) as pbar:
   for i in tqdm((foo_, range_ ), position=0, leave=True):
    pbar.update()

17
如果您在Colab的单元格顶部使用了“from functools import partial”和“from tqdm import tqdm”,然后添加“tqdm = partial(tqdm, position=0, leave=True)”,这将使得您只需调用“tqdm(iterable)”即可在Colab中良好地运行。 - Robert Bracco
2
在PyCharm中,for i in tqdm(range(n), position=0, leave=True) 对我也适用。 - Blupon
这在jupyterlab和终端中都适用。 - LI Xuhong
2
请使用tqdm.auto.tqdm而不是tqdm.tqdm。 - Vivasvan Patel
1
如果tqdm在包内部使用,这会起作用吗?我猜测不会,因为该包将有自己的from tqdm import tqdm语句或类似语句。 - Sterling
1
我不需要设置 leave=True。这似乎是默认值。 - winderland

37

我经常遇到这个问题,有时候 position = 0 & leave = True 并不能解决问题。所以,我找到了一种替代方法。

你可以使用 tqdm.auto.tqdm 替换 tqdm.tqdm
或者
替换成

from tqdm import tqdm

尝试使用

from tqdm.auto import tqdm

4
这在Jupyter Notebooks/Jupyter Lab中格式化得很好。 - Daniel Bourke
1
这也适用于VS Code笔记本。 - sea the mountains
请确认它在Google Colab中能正常运行。 - undefined

37
我发现在再次使用tqdm之前关闭tqdm实例能够解决在Jupyter Lab中打印状态栏出现换行的问题:

我发现在再次使用tqdm之前关闭tqdm实例能够解决在Jupyter Lab中打印状态栏出现换行的问题:

while len(tqdm._instances) > 0:
    tqdm._instances.pop().close()

甚至更好,感谢Nirmal的建议:

tqdm._instances.clear()

6
天啊,我一直在重启Jupyter笔记本来解决多行问题。这真的很有帮助,谢谢! - Jay Mody
这解决了它! - Vaaal88
这是最好的解决方案。谢谢! - DrRDN
这是最好的解决方案。谢谢! - undefined

35

tqdm_notebook已被弃用。您必须使用tq.notebook.tqdm替代。

import tqdm.notebook as tq
for i in tq.tqdm(...):

此外,tqdm_notebook在性能方面表现非常糟糕。但是,新的库已经完全解决了这个问题。


这将在Jupyter Lab会话中不显示进度条。 - 00__00__00
你是如何在没有使用tqdm.asyncio的情况下使用asyncio的? - huang
@00__00__00,您需要安装/更新ipywidgets并激活它Widgetspip install ipywidgets jupyter nbextension enable --py widgetsnbextension - MisterMushn

19
from tqdm import tqdm_notebook

这个命令在谷歌 Colab 中可用。


7

from tqdm import notebook

使用notebook.tqdm(looping)代替tqdm(looping)


7
尝试使用 tqdm.tqdm.write 代替标准的 print()
这将在进度条上方打印并将进度条下移一行。
我使用以下代码进行了测试,按下 space 将打印到标准输出但不会中断循环。 由于您的 interrupt() 函数只检查提供的字符串类型,因此不太清楚您要实现什么。可以参考type() 内置函数
import tqdm
import msvcrt
from time import sleep

def transfer():
    for i in tqdm.tqdm(range(1000), desc="Transfer progress", ncols=100, bar_format='{l_bar}{bar}|'):
        sleep(.1)
        if msvcrt.kbhit():
            if msvcrt.getwche() == ' ':
                interrupt()
                # break

def interrupt():
    tqdm.tqdm.write("File transfer interrupted, to restart the transfer, type 'restart'", end="")

transfer()

编辑:根据 Paul Netherwood 的指示,包括 tqdm.write()end 参数。 tqdm.tqdm.write()


4
请注意,tqdm.write() 函数有一个可选参数 'end',默认为 '\n',会导致换行。将 end='' 以避免换行。 - Paul Netherwood

6
如果您在使用tqdm时遇到了这个问题,那么...
请使用tqdm的notebook/colab版本。
>>> from tqdm.notebook import trange, tqdm
>>> for i in trange(1000):
...     ...

4
除了上述的position=0, leave=True参数外,在我的情况下,tqdm 的默认参数ascii=False也会在几次迭代后换行打印。您可以通过观察进度条来轻松识别是否出现这种情况:如果进度条中有任何奇怪格式的符号(例如问号),则应尝试使用ascii=True
所以对我有效的是:
from tqdm.auto import tqdm
...

with tqdm(data, position=0, leave=True, ascii=True) as iterator:
   for x in iterator:
      # do stuff
      ...

      iterator.set_postfix_str(msg)

4
你可能已经两次导入了tqdm。重新启动整个笔记本内核并再次运行即可解决问题。它也可能是由于在tqdm中存在任何打印语句而显示的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接