当我的脚本正在执行一些可能需要时间的任务时,我如何使用进度条?
例如,一个函数需要一段时间才能完成,完成后返回True。如何在函数执行期间显示进度条?
请注意,我需要这是实时的,所以我不知道该怎么做。我需要一根线吗?我不知道。
现在我没有打印任何东西,而函数正在执行,但一个进度条会很好。此外,我更感兴趣的是从代码的角度如何做到这一点。
当我的脚本正在执行一些可能需要时间的任务时,我如何使用进度条?
例如,一个函数需要一段时间才能完成,完成后返回True。如何在函数执行期间显示进度条?
请注意,我需要这是实时的,所以我不知道该怎么做。我需要一根线吗?我不知道。
现在我没有打印任何东西,而函数正在执行,但一个进度条会很好。此外,我更感兴趣的是从代码的角度如何做到这一点。
当前回答
下面的代码是一个相当通用的解决方案,也有一个时间消耗和剩余时间估计。你可以使用任何可迭代对象。进度条的大小固定为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)
欢迎提出改进建议或其他意见。干杯!
其他回答
如果你的工作不能被分解成可测量的块,你可以在一个新的线程中调用你的函数,并记录它所花费的时间:
import thread
import time
import sys
def work():
time.sleep( 5 )
def locked_call( func, lock ):
lock.acquire()
func()
lock.release()
lock = thread.allocate_lock()
thread.start_new_thread( locked_call, ( work, lock, ) )
# This part is icky...
while( not lock.locked() ):
time.sleep( 0.1 )
while( lock.locked() ):
sys.stdout.write( "*" )
sys.stdout.flush()
time.sleep( 1 )
print "\nWork Done"
显然,您可以根据需要提高计时精度。
PIP安装progressbar2
import os
import time
import progressbar
os.environ['PYCHARM_HOSTED'] = '1' # https://github.com/WoLpH/python-progressbar/issues/237
class COLOR: # https://stackoverflow.com/a/287944/11465149
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=…)+ this,以防你想使用它作为下载进度条
下面是一个简短的解决方案,以编程方式构建加载条(您必须决定需要多长时间)。
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()
我想我有点晚了,但这应该适用于使用当前版本的python 3的人,因为这使用了“f-strings”,正如python 3.6 PEP 498中介绍的那样:
Code
from numpy import interp
class Progress:
def __init__(self, value, end, title='Downloading',buffer=20):
self.title = title
#when calling in a for loop it doesn't include the last number
self.end = end -1
self.buffer = buffer
self.value = value
self.progress()
def progress(self):
maped = int(interp(self.value, [0, self.end], [0, self.buffer]))
print(f'{self.title}: [{"#"*maped}{"-"*(self.buffer - maped)}]{self.value}/{self.end} {((self.value/self.end)*100):.2f}%', end='\r')
例子
#some loop that does perfroms a task
for x in range(21) #set to 21 to include until 20
Progress(x, 21)
输出
Downloading: [########------------] 8/20 40.00%
一个非常简单的方法:
def progbar(count: int) -> None:
for i in range(count):
print(f"[{i*'#'}{(count-1-i)*' '}] - {i+1}/{count}", end="\r")
yield i
print('\n')
以及用法:
from time import sleep
for i in progbar(10):
sleep(0.2) #whatever task you need to do