108

我正在使用 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'")
4

16 回答 16

125

尝试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()
于 2019-07-17T09:26:24.030 回答
25

tqdm_notebook已弃用。您必须改用tq.notebook.tqdm

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

而且,tqdm_notebook在性能方面真的很惨。新图书馆完全纠正了这一点。

于 2020-01-14T18:10:33.407 回答
20
from tqdm import tqdm_notebook

此命令在 google colab 中有效。

于 2019-12-15T16:00:04.800 回答
20

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

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

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

tqdm._instances.clear()
于 2020-04-15T13:43:41.117 回答
7

我经常遇到这个问题,有时position = 0&leave = True不起作用。所以,我找到了另一种方法。您可以使用tqdm.auto.tqdm

代替tqdm.tqdm 或 代替

from tqdm import tqdm

尝试使用

from tqdm.auto import tqdm
于 2021-05-04T08:44:14.647 回答
7

from tqdm import notebook

而不是tqdm(looping)
使用notebook.tqdm(looping)

于 2020-06-02T10:32:56.793 回答
7

尝试使用tqdm.tqdm.write代替标准print()

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

我使用下面的代码对此进行了测试,按下space将打印到标准输出但不会中断循环。interrupt()由于您的功能仅检查所提供字符串的类型,因此并不是 100% 清楚您要实现的目标。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.tqdm.write()end所指出的参数tqdm.write()

于 2018-11-20T15:15:53.117 回答
4

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

于 2020-04-29T07:05:49.243 回答
3

除了上述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)
于 2021-01-19T09:32:15.753 回答
2

以下是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)

有时会在开始时打印先前的输出(我不确定如何删除),但我发现它比换行符(尤其是在长循环中)要少得多。

于 2019-08-16T23:53:50.447 回答
2

导入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将正常工作。

于 2019-11-17T15:23:16.910 回答
2

leave=False因为内循环在我的情况下有效。

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

环境与tqdm==4.38.0Python 3.6.7

于 2020-08-26T20:14:15.020 回答
0

尝试使用tqdm.tnrange()

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

正在进行的图像 完成的图像

于 2019-03-21T15:41:42.717 回答
0

https://github.com/tqdm/tqdm#parameters 我认为有时 tqdm 无法捕捉屏幕宽度使用 ncols=xx 来限制线宽 例如:tqdm(iter,ncols=80): #restrict line width=80

于 2020-11-03T02:34:41.003 回答
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 Progress Bar

于 2019-08-10T08:30:15.117 回答
-8

尝试from tqdm import tqdm_notebook as tqdm代替from tqdm import tqdm.

于 2017-10-15T16:31:18.243 回答