当我的脚本正在执行一些可能需要时间的任务时,我如何使用进度条?
例如,一个函数需要一段时间才能完成,完成后返回True。如何在函数执行期间显示进度条?
请注意,我需要这是实时的,所以我不知道该怎么做。我需要一根线吗?我不知道。
现在我没有打印任何东西,而函数正在执行,但一个进度条会很好。此外,我更感兴趣的是从代码的角度如何做到这一点。
当我的脚本正在执行一些可能需要时间的任务时,我如何使用进度条?
例如,一个函数需要一段时间才能完成,完成后返回True。如何在函数执行期间显示进度条?
请注意,我需要这是实时的,所以我不知道该怎么做。我需要一根线吗?我不知道。
现在我没有打印任何东西,而函数正在执行,但一个进度条会很好。此外,我更感兴趣的是从代码的角度如何做到这一点。
当前回答
您应该将进度条链接到手头的任务(以便它度量进度:D)。例如,如果您正在对一个文件进行ftp传输,您可以告诉ftplib获取一个特定大小的缓冲区,比如128K,然后您将128K所代表的文件大小的百分比添加到进度条中。如果您正在使用CLI,并且进度表有20个字符长,那么当文件传输了1/20时,您将添加一个字符。
其他回答
有一些特定的库(比如这里的这个),但也许一些非常简单的库就可以做到:
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()
我喜欢加布里埃尔的答案,但我改变了它的灵活性。您可以将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% 完成了。
如果你的工作不能被分解成可测量的块,你可以在一个新的线程中调用你的函数,并记录它所花费的时间:
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"
显然,您可以根据需要提高计时精度。
上面的建议非常好,但我认为大多数人只是想要一个现成的解决方案,不依赖于外部包,但也是可重用的。
我得到了上面所有的优点,并把它做成了一个函数,以及一个测试用例。
要使用它,只需复制“def update_progress(progress)”下面的行,而不是测试脚本。不要忘记导入sys。在需要显示或更新进度条时调用此函数。
这是通过直接向控制台发送“\r”符号来将光标移回起始位置。python中的"print"不能识别上述符号,因此我们需要'sys'
import time, sys
# update_progress() : Displays or updates a console progress bar
## Accepts a float between 0 and 1. Any int will be converted to a float.
## A value under 0 represents a 'halt'.
## A value at 1 or bigger represents 100%
def update_progress(progress):
barLength = 10 # Modify this to change the length of the progress bar
status = ""
if isinstance(progress, int):
progress = float(progress)
if not isinstance(progress, float):
progress = 0
status = "error: progress var must be float\r\n"
if progress < 0:
progress = 0
status = "Halt...\r\n"
if progress >= 1:
progress = 1
status = "Done...\r\n"
block = int(round(barLength*progress))
text = "\rPercent: [{0}] {1}% {2}".format( "#"*block + "-"*(barLength-block), progress*100, status)
sys.stdout.write(text)
sys.stdout.flush()
# update_progress test script
print "progress : 'hello'"
update_progress("hello")
time.sleep(1)
print "progress : 3"
update_progress(3)
time.sleep(1)
print "progress : [23]"
update_progress([23])
time.sleep(1)
print ""
print "progress : -10"
update_progress(-10)
time.sleep(2)
print ""
print "progress : 10"
update_progress(10)
time.sleep(2)
print ""
print "progress : 0->1"
for i in range(101):
time.sleep(0.1)
update_progress(i/100.0)
print ""
print "Test completed"
time.sleep(10)
这是测试脚本显示的结果(最后一个进度条是动画):
progress : 'hello'
Percent: [----------] 0% error: progress var must be float
progress : 3
Percent: [##########] 100% Done...
progress : [23]
Percent: [----------] 0% error: progress var must be float
progress : -10
Percent: [----------] 0% Halt...
progress : 10
Percent: [##########] 100% Done...
progress : 0->1
Percent: [##########] 100% Done...
Test completed