Python进度条

548

当我的脚本执行一些可能需要时间的任务时,如何使用进度条呢?

例如,在完成某个函数并返回True时需要一定的时间。我如何在函数执行期间显示进度条呢?

请注意,我需要实时显示进度条,所以我不知道该怎么办。我需要为此使用thread吗?我不知道。

目前我在函数执行期间没有任何打印输出,但一个进度条会很好。我更关心的是从代码角度如何实现这一点。


你是使用GUI工具包还是仅限于CLI? - Bobby
使用GUI可以做到这一点,但我对CLI部分感兴趣。无论如何,我可以使用第三方库。 - user225312
4
可能是重复的问题,与“在控制台中的文本进度条”有关。请注意,虽然这个问题发布时间早于另一个问题三天,但是链接的那个问题更常被查看。 - Greenstick
这是一个在Jupyter Notebook中的解决方案:https://mikulskibartosz.name/how-to-display-a-progress-bar-in-jupyter-notebook-47bd4c2944bf - Steven C. Howell
我发布了一种新型进度条,你可以打印它,查看吞吐量和预计时间,甚至可以暂停它,除此之外还有非常酷的动画效果!请查看:https://github.com/rsalmei/alive-progress alive-progress - rsalmei
我没有循环,只有一个写入命令。在这种情况下,是否可能?with open(path2file, 'wb+') as f: # with open(path2file, 'w+') as f: f.write(data.read()) - Charlie Parker
47个回答

12

我非常喜欢python-progressbar,因为它非常易于使用。

对于最简单的情况,只需要:

import progressbar
import time

progress = progressbar.ProgressBar()
for i in progress(range(80)):
    time.sleep(0.01)
外观可以自定义,并且它可以显示估计剩余时间。例如,使用与上面相同的代码,但是更改为:
progress = progressbar.ProgressBar(widgets=[progressbar.Bar('=', '[', ']'), ' ',
                                            progressbar.Percentage(), ' ',
                                            progressbar.ETA()])

8
一个简单的一行代码:
K = 628318
for k in range(K):
    # your stuff
    print(end="\r|%-80s|" % ("="*(80*(k+1)//K)))

|=====================================================================       |

80 是进度条的长度。最终你想要一个最终的 print()

它也可以放入一个方便的函数中。结合使用 yield,可以模拟 tqdm 的行为:

def progbar(iterobj):
    K = len(iterobj)
    for k, obj in enumerate(iterobj):
        print(end="\r|%-80s|" % ("="*(80*(k+1)//K)))
        yield obj
    print()
    raise StopIteration

for k in progbar(range(628318)):
    # your stuff
    pass

还有不要忘记数字进度指示器:

K = 628318
for k in range(K):
    # your stuff
    print(end=f"\r{(k+1)/K*100:6.2f} %")

 94.53 %

如果需要,将它们结合起来并不太困难。

关键在于“回车符”\r和在print中抑制默认的end="\n"


7
如果有一个循环次数固定且耗时较长的大型循环,您可以使用我制作的此函数。每个循环迭代都会增加进度。其中count是当前循环的迭代次数,total是您正在循环的值,size(int)是您想要的进度条大小,以10为增量(例如,size 1 = 10个字符,size 2 = 20个字符)。
import sys
def loadingBar(count,total,size):
    percent = float(count)/float(total)*100
    sys.stdout.write("\r" + str(int(count)).rjust(3,'0')+"/"+str(int(total)).rjust(3,'0') + ' [' + '='*int(percent/10)*size + ' '*(10-int(percent/10))*size + ']')

例子:

for i in range(0,100):
     loadingBar(i,100,2)
     #do some code 

输出:

i = 50
>> 050/100 [==========          ]

最为中立的解决方案。 - Ed J

7
请使用这个库:fishGitHub)。
用法:
>>> import fish
>>> while churning:
...     churn_churn()
...     fish.animate()

玩得开心!


可以的。你应该问开发者或留下工单:https://github.com/lericson/fish。 - Etienne

6

在Jupyter笔记本中运行时,普通的tqdm无法正常工作,因为它会将输出写在多行上。请改用以下方法:

import time
from tqdm.notebook import tqdm

for i in tqdm(range(100)):
    time.sleep(0.5)

enter image description here


6

pip install progressbar2

进度条 进度条 进度条 进度条 进度条


注:该段文字涉及安装Python包的说明,同时展示了五个相同的进度条图片。
import os
import time
import progressbar 

os.environ['PYCHARM_HOSTED'] = '1' # https://github.com/WoLpH/python-progressbar/issues/237

class COLOR: # https://dev59.com/U3VC5IYBdhLWcg3wcw0m#287944
    YELLOW    = '\033[93m'
    GREEN     = '\033[92m'
    RED       = '\033[91m'
    BOLD      = '\033[1m'
    ENDC      = '\033[0m'

widgets=[
    'FILE.JSON ',
    COLOR.YELLOW          , progressbar.Percentage()                        , COLOR.ENDC,
    COLOR.RED + COLOR.BOLD, progressbar.Bar(left=' ', marker='━', right=' '), COLOR.ENDC,
    COLOR.YELLOW          , progressbar.Timer()                             , COLOR.ENDC
]

for i in progressbar.progressbar(range(100), widgets=widgets):
    time.sleep(0.01)
    if i == 99:
        widgets[4] = COLOR.GREEN

如果想要使用下载进度条,可以使用enumerate(...progressbar(max_value=...)这个


5
下面的代码是一个相当通用的解决方案,也有时间消耗和剩余时间的估计。您可以对其使用任何可迭代对象。进度条的固定大小为25个字符,但它可以使用完整、半个和四分之一块字符以1%的步长显示更新。输出看起来像这样:
 18% |████▌                    | \ [0:00:01, 0:00:06]

示例代码:

import sys, time
from numpy import linspace

def ProgressBar(iterObj):
  def SecToStr(sec):
    m, s = divmod(sec, 60)
    h, m = divmod(m, 60)
    return u'%d:%02d:%02d'%(h, m, s)
  L = len(iterObj)
  steps = {int(x):y for x,y in zip(linspace(0, L, min(100,L), endpoint=False),
                                   linspace(0, 100, min(100,L), endpoint=False))}
  qSteps = ['', u'\u258E', u'\u258C', u'\u258A'] # quarter and half block chars
  startT = time.time()
  timeStr = '   [0:00:00, -:--:--]'
  activity = [' -',' \\',' |',' /']
  for nn,item in enumerate(iterObj):
    if nn in steps:
      done = u'\u2588'*int(steps[nn]/4.0)+qSteps[int(steps[nn]%4)]
      todo = ' '*(25-len(done))
      barStr = u'%4d%% |%s%s|'%(steps[nn], done, todo)
    if nn>0:
      endT = time.time()
      timeStr = ' [%s, %s]'%(SecToStr(endT-startT),
                             SecToStr((endT-startT)*(L/float(nn)-1)))
    sys.stdout.write('\r'+barStr+activity[nn%4]+timeStr); sys.stdout.flush()
    yield item
  barStr = u'%4d%% |%s|'%(100, u'\u2588'*25)
  timeStr = '   [%s, 0:00:00]\n'%(SecToStr(time.time()-startT))
  sys.stdout.write('\r'+barStr+timeStr); sys.stdout.flush()

# Example
s = ''
for c in ProgressBar(list('Disassemble and reassemble this string')):
  time.sleep(0.2)
  s += c
print(s)

如果您对改进意见或其他评论有任何建议,请不吝赐教。谢谢!


4

Python3很容易就能实现:

   import time
   import math

    def show_progress_bar(bar_length, completed, total):
        bar_length_unit_value = (total / bar_length)
        completed_bar_part = math.ceil(completed / bar_length_unit_value)
        progress = "*" * completed_bar_part
        remaining = " " * (bar_length - completed_bar_part)
        percent_done = "%.2f" % ((completed / total) * 100)
        print(f'[{progress}{remaining}] {percent_done}%', end='\r')

    bar_length = 30
    total = 100
    for i in range(0, total + 1):
        show_progress_bar(bar_length, i, total)
        time.sleep(0.1)

    print('\n')

4

2022年无需外部库的简单进度条实现方法

import time, sys

def progress(size):
    for item in range(size):
        if(item==0):
            print("[",end="")

        elif(item==size-1):
            print("]",end="\n")

        else:
            #main work goes here
            time.sleep(0.1)
            print("%",end="")
            sys.stdout.flush()

progress(50)


3

我喜欢这个页面

从简单的例子开始,逐步转向多线程版本。可以直接使用,无需第三方软件包。

代码将类似于这样:

import time
import sys

def do_task():
    time.sleep(1)

def example_1(n):
    for i in range(n):
        do_task()
        print '\b.',
        sys.stdout.flush()
    print ' Done!'

print 'Starting ',
example_1(10)

以下是使用线程来运行旋转加载条的示例,以便在程序运行时使用:
import sys
import time
import threading

class progress_bar_loading(threading.Thread):

    def run(self):
            global stop
            global kill
            print 'Loading....  ',
            sys.stdout.flush()
            i = 0
            while stop != True:
                    if (i%4) == 0: 
                        sys.stdout.write('\b/')
                    elif (i%4) == 1: 
                        sys.stdout.write('\b-')
                    elif (i%4) == 2: 
                        sys.stdout.write('\b\\')
                    elif (i%4) == 3: 
                        sys.stdout.write('\b|')

                    sys.stdout.flush()
                    time.sleep(0.2)
                    i+=1

            if kill == True: 
                print '\b\b\b\b ABORT!',
            else: 
                print '\b\b done!',


kill = False      
stop = False
p = progress_bar_loading()
p.start()

try:
    #anything you want to run. 
    time.sleep(1)
    stop = True
except KeyboardInterrupt or EOFError:
         kill = True
         stop = True

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