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

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

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

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


当前回答

#doesnt affect actual execution
#based on events and consumption in background
#may be that actual process completes a bit earlier than progress shows 99%
#make an instance with number of elements in a loop
#in each iteration call the method current_progress

import time
from math import ceil
import os
import sys
from threading import Thread
class progress_bar(object):
 def __init__(self,total_elements,length_bar=25):
  self.length_bar=length_bar
  self.total_elements=total_elements
  self.singleweight=(float(1)/float(total_elements))*100
  self.done=0
  self.qt=[0]
  self.call_count=0
  t=Thread(target=self.display_progress)
  t.start()
 def current_progress(self):
  self.done+=1
  self.qt=[self.done]+self.qt
 def display_progress(self):
  while True:
   try:
    done=self.qt.pop()
   except:
    continue
   else:
    self.call_count+=1
    self.progress=self.singleweight*done
    fill=ceil(self.progress)
    bar=int((fill*self.length_bar)/100)*"|"
    bar="["+bar+str(fill)+"%"
    barp=bar
    for i in range(0,self.length_bar+3-(len(bar))):
     barp=barp+"_"
    barp=barp+"]"
    if self.progress <= 100:
     os.system("clear")
     print("Progress:",barp, sep=' ', end='\n', file=sys.stdout, flush=True)
    if self.call_count == self.total_elements:
     break
  else:
   pass

其他回答

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

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

使用tqdm (conda install tqdm或pip install tqdm),你可以在一秒钟内为你的循环添加一个进度计:

from time import sleep
from tqdm import tqdm
for i in tqdm(range(10)):
    sleep(3)

 60%|██████    | 6/10 [00:18<00:12,  0.33 it/s]

此外,还有一个笔记本版本:

from tqdm.notebook import tqdm
for i in tqdm(range(100)):
    sleep(3)

您可以使用tqdm。Auto代替tqdm。笔记本电脑工作在两个终端和笔记本电脑。

tqdm。Contrib包含一些辅助函数,用于执行枚举、映射和压缩等操作。在tqdm.contrib.concurrent中有并发映射。

你甚至可以使用tqdm.contrib.telegram或tqdm.contrib.discord从jupyter笔记本断开连接后将进度发送到你的手机。

PyProg试试。PyProg是Python的一个开源库,用于创建超级可定制的进度指示器和进度条。

它目前的版本是1.0.2;它托管在Github上,在PyPI上可用(链接如下)。它与Python 3和2兼容,也可以与Qt控制台一起使用。

它真的很容易使用。以下代码:

import pyprog
from time import sleep

# Create Object
prog = pyprog.ProgressBar(" ", "", 34)
# Update Progress Bar
prog.update()

for i in range(34):
    # Do something
    sleep(0.1)
    # Set current status
    prog.set_stat(i + 1)
    # Update Progress Bar again
    prog.update()

# Make the Progress Bar final
prog.end()

会产生:

Initial State:
Progress: 0% --------------------------------------------------

When half done:
Progress: 50% #########################-------------------------

Final State:
Progress: 100% ##################################################

我实际上做了PyProg,因为我需要一个简单但超级可定制的进度条库。您可以轻松地使用:pip install pyprog安装它。

PyProg Github: https://github.com/Bill13579/pyprog 皮皮:https://pypi.python.org/pypi/pyprog/

jelde015的一个更普通的答案(当然是他的功劳)

手动更新加载条将是:

import sys
from math import *


def loadingBar(i, N, size):
    percent = float(i) / float(N)
    sys.stdout.write("\r"
                     + str(int(i)).rjust(3, '0')
                     +"/"
                     +str(int(N)).rjust(3, '0')
                     + ' ['
                     + '='*ceil(percent*size)
                     + ' '*floor((1-percent)*size)
                     + ']')

称之为:

loadingBar(7, 220, 40)

将结果:

007/220 [=                                       ]  

只要你想用当前的I值调用它。

将大小设置为条形图应有的字符数

受到许多不依赖包的答案的启发,我在这里分享我的实现。在任何循环中使用的函数都需要当前迭代数、迭代总数和初始时间。

import time    
def simple_progress_bar(i: int, n: int, init_time: float):
    avg_time = (time.time()-init_time)/(i+1)
    percent = ((i+1)/(n))*100
    print(
        end=f"\r|{'='*(int(percent))+'>'+'.'*int(100-int(percent))}|| " + \
        f"||Completion: {percent : 4.3f}% || \t "+ \
        f"||Time elapsed: {avg_time*(i+1):4.3f} seconds || \t " + \
        f"||Remaining time: {(avg_time*(n-(i+1))): 4.3f} seconds."
    )
    return



N = 325
t0 = time.time()
for k in range(N):
    # stuff goes here #
    time.sleep(0.0001)
    # stuff goes here #
    
    simple_progress_bar(k, N, t0)