Python进度条

use*_*312 257 python

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

例如,一个需要一些时间才能完成并True在完成时返回的函数.如何在执行功能期间显示进度条?

请注意,我需要实时,所以我无法弄清楚该怎么做.我需要thread这个吗?我不知道.

现在我正在执行函数时不打印任何内容,但是进度条会很好.此外,我更感兴趣的是从代码的角度来看如何做到这一点.

scl*_*cls 277

使用tqdm,您可以在一秒钟内为循环添加进度表:

In [1]: import time

In [2]: from tqdm import tqdm

In [3]: for i in tqdm(range(10)):
   ....:     time.sleep(3)

 60%|??????    | 6/10 [00:18<00:12,  0.33 it/s]
Run Code Online (Sandbox Code Playgroud)

此外,还有tqdm的图形版本,因为v2.0.0(d977a0c):

In [1]: import time

In [2]: from tqdm import tqdm_gui

In [3]: for i in tqdm_gui(range(100)):
  ....:     time.sleep(3)
Run Code Online (Sandbox Code Playgroud)

tqdm gui窗口

但是要小心,因为tqdm_gui可以引发TqdmExperimentalWarning: GUI is experimental/alpha,你可以通过使用忽略它warnings.simplefilter("ignore"),但在此之后它将忽略代码中的所有警告.

  • 这是我发现使用终端,qtconsole和笔记本电脑的唯一解决方案 (7认同)
  • @gaborous:为什么这不是最高投票的答案?这个简单的解决方案适用于终端和Jupyter笔记本,与最佳答案不同. (5认同)
  • 要在jupyter笔记本中运行,请使用“从tqdm导入tqdm_notebook作为tqdm”。否则不要将其写在一行上。 (4认同)
  • 它适用于任何可迭代的吗?我在使用字符串列表时遇到了麻烦. (3认同)
  • @JoshUsre是的它应该适用于任何迭代,目前我没有看到任何迭代它被阻塞.但是,ETA的显示(剩余时间)要求iterable具有``__len__```属性,或者用户必须向`tqdm`提供`total`参数.否则,酒吧将工作,但没有ETA. (3认同)

Chr*_*heD 162

有特定的库(像这里这样)但也许很简单的事情会做:

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 xrange(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
Run Code Online (Sandbox Code Playgroud)

注意:这个进度是一个叉进度尚未保持多年.

  • 这不适用于许多步骤... https://pypi.python.org/pypi/progress更容易使用 (11认同)
  • 这不应该是最好的答案.另一个答案(使用tqdm)至少对我来说好多了. (6认同)
  • @ GokuMcSpock9733您使用的是哪个版本的Python?Python的2`xrange`是Python的3`范围`. (5认同)
  • Python 3 中穷人的进度条:`print('■', end='',flush=True)` (5认同)
  • 我尝试了这个代码,它抛出了一个`NameError:name'xrange'未定义`错误.我错过了一个模块吗? (2认同)

rsa*_*mei 78

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

那么,你能说出你的计算函数有多少步吗?你能修改它的代码吗?

您不需要以任何方式重构或拆分它,您可以插入一些战略yields 来标记步骤,或者如果它使用for 循环,只需一个!

现在你的函数应该是这样的:

def compute():
    for i in range(1000):
        ... # process an item
        yield  # insert this and you're done!
Run Code Online (Sandbox Code Playgroud)

然后只需安装:

pip install alive-progress
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

from alive_progress import alive_bar

with alive_bar(1000) as bar:
    for i in compute():
        bar()
Run Code Online (Sandbox Code Playgroud)

获得一个很酷的进度条!

|??????????????                      | ??? 321/1000 [32%] in 8s (40.1/s, eta: 16s)
Run Code Online (Sandbox Code Playgroud)

免责声明:我是 的作者alive-progress,但它应该可以很好地解决您的问题!阅读https://github.com/rsalmei/alive-progress上的文档以了解更多信息。以下是它可以做什么的一些示例:

活生生的进步

活生生的进步

  • 这确实是我在 stackoverflow 上见过的最好的一个。 (9认同)
  • 非常光滑且易于使用。 (4认同)
  • 这太酷了,我不是典型的崇拜者,但这个库太棒了。干得好兄弟&lt;3 (3认同)
  • 爱它!jupyter 笔记本支持怎么样? (3认同)

小智 75

以上建议非常好,但我认为大多数人只是想要一个现成的解决方案,不依赖外部包,但也可以重用.

我得到了以上所有内容的最佳分数,并将其与测试用例一起变成了一个函数.

要使用它,只需复制"def update_progress(progress)"下的行,但不要复制测试脚本.不要忘记导入sys.只要您需要显示或更新进度条,请调用此方法.

这通过直接将"\ r"符号发送到控制台以将光标移回开始来工作.python中的"print"没有为此目的识别上述符号,因此我们需要'sys'

import time, sys

# update_progress() : Displays or updates a console progress bar
## Accepts a float between 0 and 1. Any int will be converted to a float.
## A value under 0 represents a 'halt'.
## A value at 1 or bigger represents 100%
def update_progress(progress):
    barLength = 10 # Modify this to change the length of the progress bar
    status = ""
    if isinstance(progress, int):
        progress = float(progress)
    if not isinstance(progress, float):
        progress = 0
        status = "error: progress var must be float\r\n"
    if progress < 0:
        progress = 0
        status = "Halt...\r\n"
    if progress >= 1:
        progress = 1
        status = "Done...\r\n"
    block = int(round(barLength*progress))
    text = "\rPercent: [{0}] {1}% {2}".format( "#"*block + "-"*(barLength-block), progress*100, status)
    sys.stdout.write(text)
    sys.stdout.flush()


# update_progress test script
print "progress : 'hello'"
update_progress("hello")
time.sleep(1)

print "progress : 3"
update_progress(3)
time.sleep(1)

print "progress : [23]"
update_progress([23])
time.sleep(1)

print ""
print "progress : -10"
update_progress(-10)
time.sleep(2)

print ""
print "progress : 10"
update_progress(10)
time.sleep(2)

print ""
print "progress : 0->1"
for i in range(101):
    time.sleep(0.1)
    update_progress(i/100.0)

print ""
print "Test completed"
time.sleep(10)
Run Code Online (Sandbox Code Playgroud)

这是测试脚本显示的结果(最后一个进度条动画):

progress : 'hello'
Percent: [----------] 0% error: progress var must be float
progress : 3
Percent: [##########] 100% Done...
progress : [23]
Percent: [----------] 0% error: progress var must be float

progress : -10
Percent: [----------] 0% Halt...

progress : 10
Percent: [##########] 100% Done...

progress : 0->1
Percent: [##########] 100% Done...
Test completed
Run Code Online (Sandbox Code Playgroud)

  • 动画测试(最后一个)应该说`在范围(101)`中不是100,进度停在99%并且从不显示完成. (9认同)

eus*_*iro 27

这个答案不依赖于外部包,我也认为大多数人只想要一块现成的代码.下面的代码可以通过自定义来调整以满足您的需求:栏进度符号'#',栏size,文本prefix等.

import sys

def progressbar(it, prefix="", size=60, file=sys.stdout):
    count = len(it)
    def show(j):
        x = int(size*j/count)
        file.write("%s[%s%s] %i/%i\r" % (prefix, "#"*x, "."*(size-x), j, count))
        file.flush()        
    show(0)
    for i, item in enumerate(it):
        yield item
        show(i+1)
    file.write("\n")
    file.flush()
Run Code Online (Sandbox Code Playgroud)

用法:

import time

for i in progressbar(range(15), "Computing: ", 40):
    time.sleep(0.1) # any calculation you need
Run Code Online (Sandbox Code Playgroud)

输出:

Computing: [################........................] 4/15
Run Code Online (Sandbox Code Playgroud)
  • 不需要第二个线程.上面的一些解决方案/包需要.例如,第二个线程可能是一个问题jupyter notebook.

  • 与任何迭代len()一起使用它意味着可以使用的任何东西.A list,dict例如任何东西['a', 'b', 'c' ... 'g']

您也可以通过更改文件,以更改输出sys.stderr例如

  • 我喜欢这个解决方案,生成器将抛出以下错误:`TypeError: object of type 'generator' has no len()` (2认同)
  • 以前应该看到这个评论,浪费时间来弄清楚如何让它与生成器一起工作。我必须说转换为列表对于大型对象可能没有帮助,因为生成器的点丢失了。(就我而言,我正在阅读 PDF 中的页面,并且不想将所有页面加载到内存中)。我很欣赏添加进度条库的简单性 (2认同)
  • 将生成器包装为列表似乎确实没有抓住重点。如果所有工作都在生成器中完成,那么进度条将不会显示进度。(tqdm 会处理这个问题,例如,除非您告诉它总数,否则不会显示百分比)有关线程问题的评论可能不是 100% 准确。对于 jupyter 笔记本来说,第二个线程不会出现问题。写入两个单独的输出是(stdout 和 stderr)。 (2认同)
  • 我制作了一个“更好”的版本,它将“#”字符替换为一个填充整个字符空间的 unicode 字符 -“█”。这是我提出的要点:https://gist.github.com/ChesterChowWOV/2b35c551b339adbf459363322aac5b4b (2认同)

Mas*_*ran 19

对于类似的应用程序(跟踪循环中的进度)我只是使用python-progressbar:

他们的例子是这样的,

from progressbar import *               # just a simple progress bar


widgets = ['Test: ', Percentage(), ' ', Bar(marker='0',left='[',right=']'),
           ' ', ETA(), ' ', FileTransferSpeed()] #see docs for other options

pbar = ProgressBar(widgets=widgets, maxval=500)
pbar.start()

for i in range(100,500+1,50):
    # here do something long at each iteration
    pbar.update(i) #this adds a little symbol at each iteration
pbar.finish()
print
Run Code Online (Sandbox Code Playgroud)

  • 你真的只是使用了“import *”吗? (7认同)
  • 为了与Python 3兼容,请尝试使用`progressbar2`软件包。上面的代码可以使用它。 (3认同)

Vla*_*lav 18

https://pypi.python.org/pypi/progress尝试进度.

from progress.bar import Bar

bar = Bar('Processing', max=20)
for i in range(20):
    # Do some work
    bar.next()
bar.finish()
Run Code Online (Sandbox Code Playgroud)

结果将是如下栏:

Processing |#############                   | 42/100
Run Code Online (Sandbox Code Playgroud)

  • 发现它不适用于笔记本电脑。 (2认同)

Rom*_*net 18

在搜索了等效的解决方案之后,我刚刚为我的需求做了一个简单的进度课程.我以为我可能会发布它.

from __future__ import print_function
import sys
import re


class ProgressBar(object):
    DEFAULT = 'Progress: %(bar)s %(percent)3d%%'
    FULL = '%(bar)s %(current)d/%(total)d (%(percent)3d%%) %(remaining)d to go'

    def __init__(self, total, width=40, fmt=DEFAULT, symbol='=',
                 output=sys.stderr):
        assert len(symbol) == 1

        self.total = total
        self.width = width
        self.symbol = symbol
        self.output = output
        self.fmt = re.sub(r'(?P<name>%\(.+?\))d',
            r'\g<name>%dd' % len(str(total)), fmt)

        self.current = 0

    def __call__(self):
        percent = self.current / float(self.total)
        size = int(self.width * percent)
        remaining = self.total - self.current
        bar = '[' + self.symbol * size + ' ' * (self.width - size) + ']'

        args = {
            'total': self.total,
            'bar': bar,
            'current': self.current,
            'percent': percent * 100,
            'remaining': remaining
        }
        print('\r' + self.fmt % args, file=self.output, end='')

    def done(self):
        self.current = self.total
        self()
        print('', file=self.output)
Run Code Online (Sandbox Code Playgroud)

示例:

from time import sleep

progress = ProgressBar(80, fmt=ProgressBar.FULL)

for x in xrange(progress.total):
    progress.current += 1
    progress()
    sleep(0.1)
progress.done()
Run Code Online (Sandbox Code Playgroud)

将打印以下内容:

[======== ] 17/80 ( 21%) 63 to go

  • 太棒了,谢谢你.顺便说一下,你可以在`__call__`的末尾添加`progress.current`,以限制与主代码中对象的交互. (3认同)

Gab*_*iel 13

我喜欢Brian Khuu的简单而不需要外部包装的答案.我改了一下所以我在这里添加我的版本:

import sys
import time


def updt(total, progress):
    """
    Displays or updates a console progress bar.

    Original source: https://stackoverflow.com/a/15860757/1391441
    """
    barLength, status = 20, ""
    progress = float(progress) / float(total)
    if progress >= 1.:
        progress, status = 1, "\r\n"
    block = int(round(barLength * progress))
    text = "\r[{}] {:.0f}% {}".format(
        "#" * block + "-" * (barLength - block), round(progress * 100, 0),
        status)
    sys.stdout.write(text)
    sys.stdout.flush()


runs = 300
for run_num in range(runs):
    time.sleep(.1)
    updt(runs, run_num + 1)
Run Code Online (Sandbox Code Playgroud)

它采用了run(total)的总数和到目前为止处理的运行次数(progress)total >= progress.结果如下:

[#####---------------] 27%
Run Code Online (Sandbox Code Playgroud)


Eya*_*l.D 8

您可以使用tqdm

from tqdm import tqdm

with tqdm(total=100, desc="Adding Users", bar_format="{l_bar}{bar} [ time left: {remaining} ]") as pbar:
    for i in range(100):
        time.sleep(3)
        pbar.update(1)
Run Code Online (Sandbox Code Playgroud)

在此示例中,进度条运行5分钟,如下所示:

Adding Users:   3%|??????                                     [ time left: 04:51 ]                                                                                                        
Run Code Online (Sandbox Code Playgroud)

您可以根据需要对其进行更改和自定义。


Fri*_*ich 8

一个简单的单行:

K = 628318
for k in range(K):
    # your stuff
    print(end="\r|%-80s|" % ("="*(80*(k+1)//K)))
Run Code Online (Sandbox Code Playgroud)
|=====================================================================       |
Run Code Online (Sandbox Code Playgroud)

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

也可以将其放入便利功能中。除了 之外yield,我们还可以模拟 的行为tqdm

|=====================================================================       |
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)
K = 628318
for k in range(K):
    # your stuff
    print(end=f"\r{(k+1)/K*100:6.2f} %")
Run Code Online (Sandbox Code Playgroud)

如果需要的话,将两者结合起来并不困难。

键是“回车”和抑制中\r的默认值。end="\n"print


Eti*_*nne 7

使用这个库:fishGitHub的)。

用法:

>>> import fish
>>> while churning:
...     churn_churn()
...     fish.animate()
Run Code Online (Sandbox Code Playgroud)

玩得开心!


lua*_*tor 7

我非常喜欢python-progressbar,因为它非常简单易用.

对于最简单的情况,它只是:

import progressbar
import time

progress = progressbar.ProgressBar()
for i in progress(range(80)):
    time.sleep(0.01)
Run Code Online (Sandbox Code Playgroud)

外观可以定制,它可以显示估计的剩余时间.例如,使用与上面相同的代码,但是:

progress = progressbar.ProgressBar(widgets=[progressbar.Bar('=', '[', ']'), ' ',
                                            progressbar.Percentage(), ' ',
                                            progressbar.ETA()])
Run Code Online (Sandbox Code Playgroud)


jel*_*015 6

如果它是一个需要大量时间的固定迭代次数的大循环,您可以使用我制作的这个函数。循环的每次迭代都会增加进度。其中 count 是循环的当前迭代,total 是您要循环到的值, size(int) 是您希望以 10 为增量的条的大小,即(大小 1 = 10 个字符,大小 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 + ']')
Run Code Online (Sandbox Code Playgroud)

例子:

for i in range(0,100):
     loadingBar(i,100,2)
     #do some code 
Run Code Online (Sandbox Code Playgroud)

输出:

i = 50
>> 050/100 [==========          ]
Run Code Online (Sandbox Code Playgroud)


Jac*_*ADE 6

在 jupyter 笔记本中运行时,使用普通 tqdm 不起作用,因为它会在多行上写入输出。使用这个代替:

import time
from tqdm.notebook import tqdm

for i in tqdm(range(100)):
    time.sleep(0.5)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


Gio*_*Xou 6

pip install progressbar2

\n

进度条\n进度条\n进度条\n进度条\n进度条

\n
import os\nimport time\nimport progressbar \n\nos.environ[\'PYCHARM_HOSTED\'] = \'1\' # https://github.com/WoLpH/python-progressbar/issues/237\n\nclass COLOR: # https://stackoverflow.com/a/287944/11465149\n    YELLOW    = \'\\033[93m\'\n    GREEN     = \'\\033[92m\'\n    RED       = \'\\033[91m\'\n    BOLD      = \'\\033[1m\'\n    ENDC      = \'\\033[0m\'\n\nwidgets=[\n    \'FILE.JSON \',\n    COLOR.YELLOW          , progressbar.Percentage()                        , COLOR.ENDC,\n    COLOR.RED + COLOR.BOLD, progressbar.Bar(left=\' \', marker=\'\xe2\x94\x81\', right=\' \'), COLOR.ENDC,\n    COLOR.YELLOW          , progressbar.Timer()                             , COLOR.ENDC\n]\n\nfor i in progressbar.progressbar(range(100), widgets=widgets):\n    time.sleep(0.01)\n    if i == 99:\n        widgets[4] = COLOR.GREEN\n
Run Code Online (Sandbox Code Playgroud)\n

如果您想将其用作下载进度条,请使用enumerate(...progressbar(max_value=...)+ this

\n


Nik*_*iko 5

下面的代码是一个非常通用的解决方案,并且还有一个已用时间和剩余时间估计。您可以使用任何可迭代对象。进度条的固定大小为 25 个字符,但它可以使用完整、半个和四分之一块字符以 1% 的步长显示更新。输出如下所示:

 18% |?????                    | \ [0:00:01, 0:00:06]
Run Code Online (Sandbox Code Playgroud)

代码示例:

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)
Run Code Online (Sandbox Code Playgroud)

对改进或其他意见的建议表示赞赏。干杯!