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

例如,一个函数需要一段时间才能完成,完成后返回True。如何在函数执行期间显示进度条?

请注意,我需要这是实时的,所以我不知道该怎么做。我需要一根线吗?我不知道。

现在我没有打印任何东西,而函数正在执行,但一个进度条会很好。此外,我更感兴趣的是从代码的角度如何做到这一点。


当前回答

使用动态进度,最酷的进度条!

要以一种有用的方式使用任何进度条框架,即获得完成百分比和预计到达时间(ETA),您需要能够告诉您的处理将有多少步骤。

然后,您只需插入一个yield来标记一个项目已被处理,然后就可以开始了!

def compute():
    for i in range(1000):
        ... # process items as usual.
        yield  # insert this :)

然后就像这样使用它:

from alive_progress import alive_bar

with alive_bar(1000) as bar:
    for i in compute():
        bar()

获得一个令人敬畏的和活着的进度条!

|█████████████▎                      | ▅▃▁ 321/1000 [32%] in 8s (40.1/s, eta: 16s)

披露:我是alive-progress的作者,但它应该能很好地解决你的问题!阅读https://github.com/rsalmei/alive-progress上的文档了解更多信息。现在它也在木星笔记本!以下是它能做的更多例子:

其他回答

有一些特定的库(比如这里的这个),但也许一些非常简单的库就可以做到:

import time
import sys

toolbar_width = 40

# setup toolbar
sys.stdout.write("[%s]" % (" " * toolbar_width))
sys.stdout.flush()
sys.stdout.write("\b" * (toolbar_width+1)) # return to start of line, after '['

for i in range(toolbar_width):
    time.sleep(0.1) # do real work here
    # update the bar
    sys.stdout.write("-")
    sys.stdout.flush()

sys.stdout.write("]\n") # this ends the progress bar

注意:progressbar2是progressbar的一个分支,已经很多年没有维护过了。

下面是一个简短的解决方案,以编程方式构建加载条(您必须决定需要多长时间)。

import time

n = 33  # or however many loading slots you want to have
load = 0.01  # artificial loading time!
loading = '.' * n  # for strings, * is the repeat operator

for i in range(n+1):
    # this loop replaces each dot with a hash!
    print('\r%s Loading at %3d percent!' % (loading, i*100/n), end='')
    loading = loading[:i] + '#' + loading[i+1:]
    time.sleep(load)
    if i==n: print()

已经有很多令人惊叹的答案,但我想分享我对进度条的解决方案。

from time import sleep

def progress_bar(progress: float, total: float, width: int = 25):
    percent = width * ((progress + 1) / total)
    bar = chr(9608) * int(percent) + "-" * (width - int(percent))
    print(f"\r|{bar}| {(100/width)*percent:.2f}%", end="\r")

numbers = range(0, 1000)
numbersLen = len(numbers)
for i in numbers:
    sleep(0.01) # Do something usefull here
    progress_bar(i, numbersLen)

编辑:

如果你正在寻找一个条,调整它是基于终端的宽度和可能的消息在结束,然后这也是工作。请注意,如果终端太窄,消息将消失,因为如果它太宽,竖条将断开。

def progressBar(progress: float, total: float, message: str = ""):
    terminalWidth = get_terminal_size().columns
    width = int(terminalWidth / 4)
    percent = width * ((progress + 1) / total)
    bar = chr(9608) * int(percent) + "-" * (width - int(percent))
    if terminalWidth <= 40:
        message = ""
    else:
        message = message + (" " * (int(terminalWidth / 2) - len(message)))
    print(f"\r|{bar}| {(100/width)*percent:.2f}% " + message, end="\r")

使用这个库:fish (GitHub)。

用法:

>>> import fish
>>> while churning:
...     churn_churn()
...     fish.animate()

玩得开心!

下面的代码是一个相当通用的解决方案,也有一个时间消耗和剩余时间估计。你可以使用任何可迭代对象。进度条的大小固定为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)

欢迎提出改进建议或其他意见。干杯!