当我的脚本正在执行一些可能需要时间的任务时,我如何使用进度条?
例如,一个函数需要一段时间才能完成,完成后返回True。如何在函数执行期间显示进度条?
请注意,我需要这是实时的,所以我不知道该怎么做。我需要一根线吗?我不知道。
现在我没有打印任何东西,而函数正在执行,但一个进度条会很好。此外,我更感兴趣的是从代码的角度如何做到这一点。
当我的脚本正在执行一些可能需要时间的任务时,我如何使用进度条?
例如,一个函数需要一段时间才能完成,完成后返回True。如何在函数执行期间显示进度条?
请注意,我需要这是实时的,所以我不知道该怎么做。我需要一根线吗?我不知道。
现在我没有打印任何东西,而函数正在执行,但一个进度条会很好。此外,我更感兴趣的是从代码的角度如何做到这一点。
当前回答
一个简单的联机程序:
K = 628318
for k in range(K):
# your stuff
print(end="\r|%-80s|" % ("="*int(80*k/(K-1))))
|===================================================================== |
80是棒子的长度。最终,您需要一个最终的print()。
不要忘了数字进步指示器:
K = 628318
for k in range(K):
# your stuff
print(end="\r%6.2f %%" % (k/(K-1)*100))
94.53 %
如果需要,将两者结合起来并不难。
键是“回车”\r和打印中默认end=“\n”的抑制键。
其他回答
没有外部包。一段现成的代码。
您可以自定义进度条符号“#”,进度条大小,文本前缀等。
Python 3.3 +
import sys
def progressbar(it, prefix="", size=60, out=sys.stdout): # Python3.3+
count = len(it)
def show(j):
x = int(size*j/count)
print("{}[{}{}] {}/{}".format(prefix, "#"*x, "."*(size-x), j, count),
end='\r', file=out, flush=True)
show(0)
for i, item in enumerate(it):
yield item
show(i+1)
print("\n", flush=True, file=out)
用法:
import time
for i in progressbar(range(15), "Computing: ", 40):
time.sleep(0.1) # any code you need
要填满整个字符空间,请使用unicode u"█"字符替换"#"。使用for i in progressbar(range(100)):…你会得到:
不需要第二个线程。上面的一些解决方案/包需要。 适用于任何可迭代对象,它指的是任何可以使用len()的对象。一个列表,一个字典,比如[' A ', 'b', 'c'…' g '] 使用生成器的工作只需要用list()来包装它。例如,对于i in progressbar(list(your_generator), "Computing: ", 40):除非工作在生成器中完成。在这种情况下,您需要另一种解决方案(如tqdm)。
您还可以通过将out更改为sys来更改输出。例如Stderr。
Python 3.6+ (f-string)
def progressbar(it, prefix="", size=60, out=sys.stdout): # Python3.6+
count = len(it)
def show(j):
x = int(size*j/count)
print(f"{prefix}[{u'█'*x}{('.'*(size-x))}] {j}/{count}", end='\r', file=out, flush=True)
show(0)
for i, item in enumerate(it):
yield item
show(i+1)
print("\n", flush=True, file=out)
Python 2 (old-code)
import sys
def progressbar(it, prefix="", size=60, out=sys.stdout):
count = len(it)
def show(j):
x = int(size*j/count)
out.write("%s[%s%s] %i/%i\r" % (prefix, u"#"*x, "."*(size-x), j, count))
out.flush()
show(0)
for i, item in enumerate(it):
yield item
show(i+1)
out.write("\n")
out.flush()
如果你的工作不能被分解成可测量的块,你可以在一个新的线程中调用你的函数,并记录它所花费的时间:
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"
显然,您可以根据需要提高计时精度。
这里有一个简单的解决方案!
void = '-'
fill = '#'
count = 100/length
increaseCount = 0
for i in range(length):
print('['+(fill*i)+(void*(length-i))+'] '+str(int(increaseCount))+'%',end='\r')
increaseCount += count
time.sleep(0.1)
print('['+(fill*(i+1))+(void*(length-(i+1)))+'] '+str(int(increaseCount))+'%',end='\n')
注意:如果需要,可以修改fill和“void”字符。
加载条(图片)
试试https://pypi.python.org/pypi/progress上的progress。
from progress.bar import Bar
bar = Bar('Processing', max=20)
for i in range(20):
# Do some work
bar.next()
bar.finish()
结果将是如下所示的条:
Processing |############# | 42/100
我喜欢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)
它取总运行次数(total)和目前处理的运行次数(progress),假设total >= progress。结果如下所示:
[#####---------------] 27%