【问题标题】:tqdm printing to newlinetqdm 打印到换行符
【发布时间】:2017-06-02 02:41:16
【问题描述】:

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

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

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

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


【解决方案1】:

试试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()

【讨论】:

  • 如果您在笔记本顶部使用from functools import partialfrom tqdm import tqdmtqdm = partial(tqdm, position=0, leave=True) 创建一个colab 单元,这将进行设置,因此您只需调用tqdm(iterable) 即可很好地在 colab 中。
  • for i in tqdm(range(n), position=0, leave=True) 在 PyCharm 中也适用于我
  • 这也适用于 jupyterlab 和终端。
  • 而不是 tqdm.tqdm。使用 tqdm.auto.tqdm
【解决方案2】:

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

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

另外,tqdm_notebook在性能方面真的很惨。新库完全纠正了这一点。

【讨论】:

  • 这在 jupyter Lab 会话中不显示进度条
  • 在没有tqdm.asyncio 的情况下,您如何使用asyncio
【解决方案3】:
from tqdm import tqdm_notebook

此命令在 google colab 中有效。

【讨论】:

    【解决方案4】:

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

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

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

    tqdm._instances.clear()
    

    【讨论】:

    • 该死,我一直在重新启动 Jupyter 笔记本来修复多行问题。这真的很有帮助,谢谢!
    【解决方案5】:

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

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

    我使用下面的代码对此进行了测试,按下space 将打印到标准输出但不会中断循环。 由于您的 interrupt() 函数仅检查所提供字符串的类型,因此您要达到的目标并不是 100% 清楚。 type() built-in function

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

    编辑:包括 tqdm.write()end 参数,如 Paul Netherwood 所述 tqdm.tqdm.write()

    【讨论】:

    • 请注意,tqdm.write() 有一个可选参数 'end',默认为 '\n',这将导致换行。设置 end=''
    【解决方案6】:

    from tqdm import notebook

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

    【讨论】:

      【解决方案7】:

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

      您可以使用 tqdm.auto.tqdm
      而不是 tqdm.tqdm
      而不是

      from tqdm import tqdm
      

      尝试使用

      from tqdm.auto import tqdm
      

      【讨论】:

        【解决方案8】:

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

        【讨论】:

          【解决方案9】:

          以下内容很老套,但似乎可以很好地重置 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)
          

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

          【讨论】:

          • 这个很好用,谢谢
          【解决方案10】:

          导入tqdm

          from tqdm import tqdm
          

          首先启动代码,在你使用tqdm的地方,因为多行输出而停止它。

          然后做:

          list(getattr(tqdm, '_instances'))
          
          for instance in list(tqdm._instances):
              tqdm._decr_instances(instance)
          

          如果出现错误:

          AttributeError: type object 'tqdm' has no attribute '_instances'

          您需要首先启动您的代码,使用tqdm 并且仅在提及的启动代码之后。

          在所有这些操作之后,您的 tqdm 将正常工作。

          【讨论】:

            【解决方案11】:

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

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

            tqdm==4.38.0Python 3.6.7 的环境

            【讨论】:

              【解决方案12】:

              除了前面提到的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)
              

              【讨论】:

                【解决方案13】:

                尝试使用tqdm.tnrange()

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

                【讨论】:

                • 请将代码包含为代码块而不是图像,以便更容易复制/粘贴(并降低 Stack Overflow 的托管成本)
                • 抱歉,代码 for i in tqdm.tnrange(len(df)): rest 是用于 jupyter 的,因为换行符也发生在 notebook 中。
                【解决方案14】:

                我已经尝试过 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

                【讨论】:

                  【解决方案15】:

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

                  【讨论】:

                    【解决方案16】:

                    尝试from tqdm import tqdm_notebook as tqdm 而不是from tqdm import tqdm

                    【讨论】:

                    • 真的吗?这适用于 jupyter/ipython 笔记本,在这里似乎并不适用。
                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2019-08-15
                    • 1970-01-01
                    • 2011-01-02
                    • 1970-01-01
                    相关资源
                    最近更新 更多