当我的脚本正在执行一些可能需要时间的任务时,我如何使用进度条?
例如,一个函数需要一段时间才能完成,完成后返回True。如何在函数执行期间显示进度条?
请注意,我需要这是实时的,所以我不知道该怎么做。我需要一根线吗?我不知道。
现在我没有打印任何东西,而函数正在执行,但一个进度条会很好。此外,我更感兴趣的是从代码的角度如何做到这一点。
当我的脚本正在执行一些可能需要时间的任务时,我如何使用进度条?
例如,一个函数需要一段时间才能完成,完成后返回True。如何在函数执行期间显示进度条?
请注意,我需要这是实时的,所以我不知道该怎么做。我需要一根线吗?我不知道。
现在我没有打印任何东西,而函数正在执行,但一个进度条会很好。此外,我更感兴趣的是从代码的角度如何做到这一点。
当前回答
这在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')
其他回答
上面的建议非常好,但我认为大多数人只是想要一个现成的解决方案,不依赖于外部包,但也是可重用的。
我得到了上面所有的优点,并把它做成了一个函数,以及一个测试用例。
要使用它,只需复制“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)
这是测试脚本显示的结果(最后一个进度条是动画):
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
下面的代码是一个相当通用的解决方案,也有一个时间消耗和剩余时间估计。你可以使用任何可迭代对象。进度条的大小固定为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)
欢迎提出改进建议或其他意见。干杯!
它在我的程序中工作得很好。此外,我们需要添加一个计数器来指示循环时间。这个计数器作为方法update的参数。 例如:读取测试文件的所有行,并对它们进行处理。假设函数dosth()与变量i无关。
lines = open(sys.argv[1]).readlines()
i = 0
widgets=[Percentage(), Bar()]
pbar = ProgressBar(widgets=widgets,maxval=len(lines)).start()
pbar.start()
for line in lines:<pre>
dosth();
i += 1
pbar.update(i)</pre>
pbar.finish()
变量i通过方法update控制pbar的状态
这是我的简单解决方案:
import time
def progress(_cur, _max):
p = round(100*_cur/_max)
b = f"Progress: {p}% - ["+"."*int(p/5)+" "*(20-int(p/5))+"]"
print(b, end="\r")
# USAGE:
for i in range(0,101):
time.sleep(0.1)
progress(i,100)
print("..."*5, end="\r")
print("Done")
这里有一个非常简单的版本,如果你有一个循环,只是想了解迭代的进展,比如每一个点,比如说,5000次迭代。
my_list = range(0,100000)
counter = 0
for x in my_list:
#your code here
counter = counter + 1
if counter % 5000 == 0:
print(".", end="") # end="" avoids a newline, keeps dots together
print() #this makes sure whatever you print next is in a new line
My_list不是方案的一部分。使用你自己的迭代对象,不管你在循环什么。 这个版本没有提前告诉您总共有多少次迭代。