当我运行一个长的python程序时,我想显示一个进度条。我在线研究,发现下面的功能。
import sys, time
def progress(count, total, status=''):
bar_len = 60
filled_len = int(round(bar_len * count / float(total)))
percents = round(100.0 * count / float(total), 1)
bar = '=' * filled_len + '-' * (bar_len - filled_len)
sys.stdout.write('\r[%s] %s%s ...%s\r' % (bar, percents, '%', status))
sys.stdout.flush()
然后,我执行了以下操作:
total = 1000
i = 0
while i < total:
progress(i, total, status='Doing very long job')
# My long python program here
i += 1
当我尝试上述操作时,运行我的python程序会花费更长的时间。以上是使用progress
函数并显示进度条的正确方法吗?感谢您的投入。
答案 0 :(得分:1)
执行中花费的额外时间归因于频繁(1000x)控制台刷新。 请阅读以下问题:Why is printing to stdout so slow? Can it be sped up?
为解决此问题,我建议打印状态并每隔例如10或20次迭代:
total = 1000
i = 0
while i < total:
if i % 20 == 0:
progress(i, total, status='Doing very long job')
# My long python program here
i += 1
但是,最好的方法是使用现有的库,例如tqdm(https://github.com/tqdm/tqdm)。它经过了优化,并提供了很酷的功能,例如嵌套的进度条。
答案 1 :(得分:0)
如果第三方库可以,我建议使用tqdm。另外,在询问性能时,如果您报告时间安排也会很有帮助。
提高性能的一种方法是不对循环的每次迭代都调用进度。 IO很昂贵,因此不断打印到屏幕上确实会使程序陷入瘫痪,尤其是如果您通过使用flush绕过缓冲。
答案 2 :(得分:0)
我编写了一个简单的进度条代码来显示类似这样的内容:
[############# 4 ------] 67.00%
要与FOR或WHILE一起放置,但您需要知道总大小:
class Progresso:
def __init__(self, total, steps):
assert steps < 101 and type(total) == int and type(steps) == int and total > steps
self.count = 0
self.total = total
self.steps = steps
self.passo = total // steps
if total < steps *10:
self.test = 1
else:
self.test = total // (steps * 10)
print(self.prog(), end='\r')
def printa(self):
self.count += 1
if self.count % self.test == 0:
print(self.prog(), end='\r')
def prog(self):
passado = self.count // self.passo
fut = self.steps - passado + 1
resto = int((self.count % self.passo) / self.passo * 10)
if resto == 0:
centro = '-'*(fut -1)
else:
centro = str(resto) + '-'*(fut-2)
return '['+'#'*passado + centro + '] ' +'{:.2f}% '.format(self.count/self.total*100)
def fim(self):
self.count = self.total
print(self.prog())
您像这样在FOR / WHILE之前开始:
p = Progresso(200000, 20)
在FOR / WHILE内插入 p.printa(),然后在FOR / WHILE后插入 p.fim()。
答案 3 :(得分:0)
对进度功能进行相当简单的更改,通过将先前打印的条保存在函数属性中(请参见https://www.python.org/dev/peps/pep-0232/),可以确保仅在进度条已更改时才打印和刷新(见{{3}}):
import sys, time
def progress(count, total, status=''):
# make sure the saved bar is initialized
if not hasattr(progress,'lastbar'):
progress.lastbar = ""
bar_len = 60
filled_len = int(round(bar_len * count / float(total)))
percents = round(100.0 * count / float(total), 1)
bar = '=' * filled_len + '-' * (bar_len - filled_len)
# only print the bar if it is different from the previous bar
if bar != progress.lastbar:
sys.stdout.write('\r[%s] %s%s ...%s\r' % (bar, percents, '%', status))
sys.stdout.flush()
progress.lastbar = bar
total = 1000
i = 0
while i < total:
progress(i, total, status='Doing very long job')
# My long python program here
i += 1
上面的代码仅在条形本身已更改时打印和刷新-因此是60次而不是1000次-忽略了所显示的百分比和状态消息的更改-如果这些对您来说很重要,则您可能希望存储和比较完整的像这样的打印行(但这将执行更多的打印和更多的冲洗操作):
import sys, time
def progress(count, total, status=''):
if not hasattr(progress,'lastbar'):
progress.lastbar = ""
bar_len = 60
filled_len = int(round(bar_len * count / float(total)))
percents = round(100.0 * count / float(total), 1)
bar = '=' * filled_len + '-' * (bar_len - filled_len)
fullbar = '\r[%s] %s%s ...%s\r' % (bar, percents, '%', status)
if fullbar != progress.lastbar:
sys.stdout.write(fullbar)
sys.stdout.flush()
progress.lastbar = fullbar
total = 1000
i = 0
while i < total:
progress(i, total, status='Doing very long job')
# My long python program here
i += 1
我敢肯定,也可以使用更复杂的方法在进度函数中构建“ 20分之一”逻辑。
建立进度条也可能是进度功能中昂贵的一部分-您可以通过将filled_len
与先前的filled_len
进行比较来避免输出不变时避免这种情况,并且不要如果值没有改变,甚至不会构建条形字符串,如下所示:
import sys, time
def progress(count, total, status=''):
if not hasattr(progress,'lastlen'):
progress.lastlen = 0
bar_len = 60
filled_len = int(round(bar_len * count / float(total)))
if filled_len != progress.lastlen:
percents = round(100.0 * count / float(total), 1)
bar = '=' * filled_len + '-' * (bar_len - filled_len)
fullbar = '\r[%s] %s%s ...%s\r' % (bar, percents, '%', status)
sys.stdout.write(fullbar)
sys.stdout.flush()
progress.lastlen = filled_len
total = 1000
i = 0
while i < total:
progress(i, total, status='Doing very long job')
# My long python program here
i += 1