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

问题描述 投票:0回答:20

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

如何让它在同一行显示进度?

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

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'")
python progress-bar tqdm
20个回答
172
投票

尝试使用

position=0
leave=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()

42
投票

我经常遇到这个问题,有时

position = 0
leave = True
不起作用。所以,我找到了一种替代方法。

您可以使用 tqdm.auto.tqdm 代替 tqdm.tqdm

而不是

from tqdm import tqdm

尝试使用

from tqdm.auto import tqdm

37
投票

我意识到,在再次使用 tqdm 之前关闭 tqdm 实例可以解决 Jupyter Lab 上在新行中打印状态栏的问题:

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

或者更好,感谢 Nirmal 的建议:

tqdm._instances.clear()

35
投票

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

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

此外,tqdm_notebook 在性能方面确实很糟糕。新库完全纠正了这一问题。


19
投票
from tqdm import tqdm_notebook

此命令适用于 google colab。


7
投票

尝试使用

tqdm.tqdm.write
代替标准
print()

这将打印在进度条上方,并将进度条移至下方一行。

我使用下面的代码对此进行了测试,按

space
将打印到标准输出,但不会中断循环。 并不是 100% 清楚您想要实现的目标,因为您的
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 指出的

end
tqdm.write()
参数 tqdm.tqdm.write()


7
投票

from tqdm import notebook

而不是

tqdm(looping)

使用
notebook.tqdm(looping)


6
投票

如果您在colab或jupyter笔记本上使用

tqdm
时遇到此问题,那么...

使用笔记本/colab版本的

tqdm

>>> from tqdm.notebook import trange, tqdm
>>> for i in trange(1000):
...     ...

5
投票

除了前面提到的

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 内的任何打印语句而显示


3
投票

以下是 hacky,但似乎可以很好地重置 tqdm:

from tqdm import tqdm as tqdm_base
def tqdm(*args, **kwargs):
    if hasattr(tqdm_base, '_instances'):
        for instance in list(tqdm_base._instances):
            tqdm_base._decr_instances(instance)
    return tqdm_base(*args, **kwargs)

有时以前的输出会在开始时打印(我不知道如何删除),但我发现它比换行符更不烦人(尤其是在长循环中)。


3
投票

导入

tqdm

from tqdm import tqdm

首先启动代码,在使用

tqdm
的地方,因为多行输出而停止。

然后做:

list(getattr(tqdm, '_instances'))

for instance in list(tqdm._instances):
    tqdm._decr_instances(instance)

如果出现错误:

AttributeError:类型对象“tqdm”没有属性“_instances”

您需要首先启动您的代码,在其中使用tqdm

,并且仅在提到的启动代码之后。

完成所有这些操作后,您的

tqdm

 将会正常工作。


3
投票
我遇到的问题可能并不常见,但为了以防万一它对任何人都有用,我正在将另一个变量打印到控制台。禁用该打印可以解决问题。


2
投票

leave=False

 对于我的情况,内部循环有效。

for j in tqdm(outer_list): for i in tqdm(inner_list, leave=False):

tqdm==4.38.0

Python 3.6.7
的环境
    


1
投票
虽然最初的问题看起来是针对 Linux shell 的。从

Windows 命令行,可以执行以下操作。

from tqdm import tqdm for x in tqdm([1,2,3,4], leave=True, ncols=80, position=0): pass for y in tqdm([1,2,3,4], leave=False, ncols=80, position=1): pass
我觉得如果我阅读文档,而不是盲目地尝试所有建议的修复,我会更快地进行排序!


0
投票
尝试使用

tqdm.tnrange()



for i in tqdm.tnrange(len(df)):




0
投票
我已经尝试过 tqdm 解决方案,但由于我使用的是 Spyder (Anaconda),它在我的情况下不起作用,因为其他答案中提到写入和打印命令之间存在冲突。我想出了一个简单且可行的解决方案,尽管不是最奇特的解决方案。

def ybar(progr, total, step=50): #starts with 1 l2=(progr/total)//(1/step) if progr==1: print(f'[{total}]: '+'|'*int(l2), end = '') else: l1=((progr-1)/total)//(1/step) ll=int(l2-l1) if l1 < l2: for j in range(1,ll+1): if (int(l1)+j)%5==0: print('*', end = '') else: print('|', end = '') if progr==total: print(" DONE")

结果你会变得简单:[100]:

||||||

for i in range(1,101): ybar(i,len(range(1,101)),50) #something

这里有很多解决方案:

Python进度条



0
投票
尝试使用

leave=True

position=1

在 Kaggle 为我工作。


-8
投票
尝试用

from tqdm import tqdm_notebook as tqdm

 代替 
from tqdm import tqdm

© www.soinside.com 2019 - 2024. All rights reserved.