当我的脚本正在执行一些可能需要时间的任务时,我如何使用进度条?
例如,一个函数需要一段时间才能完成,完成后返回True。如何在函数执行期间显示进度条?
请注意,我需要这是实时的,所以我不知道该怎么做。我需要一根线吗?我不知道。
现在我没有打印任何东西,而函数正在执行,但一个进度条会很好。此外,我更感兴趣的是从代码的角度如何做到这一点。
当我的脚本正在执行一些可能需要时间的任务时,我如何使用进度条?
例如,一个函数需要一段时间才能完成,完成后返回True。如何在函数执行期间显示进度条?
请注意,我需要这是实时的,所以我不知道该怎么做。我需要一根线吗?我不知道。
现在我没有打印任何东西,而函数正在执行,但一个进度条会很好。此外,我更感兴趣的是从代码的角度如何做到这一点。
当前回答
它在我的程序中工作得很好。此外,我们需要添加一个计数器来指示循环时间。这个计数器作为方法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的状态
其他回答
我喜欢加布里埃尔的答案,但我改变了它的灵活性。您可以将bar-length发送到函数,并获得您想要的任何长度的进度条。进度条的长度不能为零或负。同样,你也可以像Gabriel answer一样使用这个函数(请看例子#2)。
import sys
import time
def ProgressBar(Total, Progress, BarLength=20, ProgressIcon="#", BarIcon="-"):
try:
# You can't have a progress bar with zero or negative length.
if BarLength <1:
BarLength = 20
# Use status variable for going to the next line after progress completion.
Status = ""
# Calcuting progress between 0 and 1 for percentage.
Progress = float(Progress) / float(Total)
# Doing this conditions at final progressing.
if Progress >= 1.:
Progress = 1
Status = "\r\n" # Going to the next line
# Calculating how many places should be filled
Block = int(round(BarLength * Progress))
# Show this
Bar = "[{}] {:.0f}% {}".format(ProgressIcon * Block + BarIcon * (BarLength - Block), round(Progress * 100, 0), Status)
return Bar
except:
return "ERROR"
def ShowBar(Bar):
sys.stdout.write(Bar)
sys.stdout.flush()
if __name__ == '__main__':
print("This is a simple progress bar.\n")
# Example #1:
print('Example #1')
Runs = 10
for i in range(Runs + 1):
progressBar = "\rProgress: " + ProgressBar(10, i, Runs)
ShowBar(progressBar)
time.sleep(1)
# Example #2:
print('\nExample #2')
Runs = 10
for i in range(Runs + 1):
progressBar = "\rProgress: " + ProgressBar(10, i, 20, '|', '.')
ShowBar(progressBar)
time.sleep(1)
print('\nDone.')
# Example #2:
Runs = 10
for i in range(Runs + 1):
ProgressBar(10, i)
time.sleep(1)
结果:
这是一个简单的进度条。 示例# 1 进度:[###-------]30% 例# 2 进步 : [||||||||||||........) 60% 完成了。
使用动态进度,最酷的进度条!
要以一种有用的方式使用任何进度条框架,即获得完成百分比和预计到达时间(ETA),您需要能够告诉您的处理将有多少步骤。
然后,您只需插入一个yield来标记一个项目已被处理,然后就可以开始了!
def compute():
for i in range(1000):
... # process items as usual.
yield # insert this :)
然后就像这样使用它:
from alive_progress import alive_bar
with alive_bar(1000) as bar:
for i in compute():
bar()
获得一个令人敬畏的和活着的进度条!
|█████████████▎ | ▅▃▁ 321/1000 [32%] in 8s (40.1/s, eta: 16s)
披露:我是alive-progress的作者,但它应该能很好地解决你的问题!阅读https://github.com/rsalmei/alive-progress上的文档了解更多信息。现在它也在木星笔记本!以下是它能做的更多例子:
你也可以用启迪。主要的优点是你可以在不覆盖进度条的同时记录日志。
import time
import enlighten
manager = enlighten.Manager()
pbar = manager.counter(total=100)
for num in range(1, 101):
time.sleep(0.05)
print('Step %d complete' % num)
pbar.update()
它还可以处理多个进度条。
import time
import enlighten
manager = enlighten.Manager()
odds = manager.counter(total=50)
evens = manager.counter(total=50)
for num in range(1, 101):
time.sleep(0.05)
if num % 2:
odds.update()
else:
evens.update()
如果你的工作不能被分解成可测量的块,你可以在一个新的线程中调用你的函数,并记录它所花费的时间:
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"
显然,您可以根据需要提高计时精度。
有一些特定的库(比如这里的这个),但也许一些非常简单的库就可以做到:
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 range(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
注意:progressbar2是progressbar的一个分支,已经很多年没有维护过了。