当我的脚本正在执行一些可能需要时间的任务时,我如何使用进度条?
例如,一个函数需要一段时间才能完成,完成后返回True。如何在函数执行期间显示进度条?
请注意,我需要这是实时的,所以我不知道该怎么做。我需要一根线吗?我不知道。
现在我没有打印任何东西,而函数正在执行,但一个进度条会很好。此外,我更感兴趣的是从代码的角度如何做到这一点。
当我的脚本正在执行一些可能需要时间的任务时,我如何使用进度条?
例如,一个函数需要一段时间才能完成,完成后返回True。如何在函数执行期间显示进度条?
请注意,我需要这是实时的,所以我不知道该怎么做。我需要一根线吗?我不知道。
现在我没有打印任何东西,而函数正在执行,但一个进度条会很好。此外,我更感兴趣的是从代码的角度如何做到这一点。
当前回答
你也可以用启迪。主要的优点是你可以在不覆盖进度条的同时记录日志。
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 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")
有一些特定的库(比如这里的这个),但也许一些非常简单的库就可以做到:
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的一个分支,已经很多年没有维护过了。
没有外部包。一段现成的代码。
您可以自定义进度条符号“#”,进度条大小,文本前缀等。
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 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"
显然,您可以根据需要提高计时精度。