当我的脚本正在执行一些可能需要时间的任务时,我如何使用进度条?

例如,一个函数需要一段时间才能完成,完成后返回True。如何在函数执行期间显示进度条?

请注意,我需要这是实时的,所以我不知道该怎么做。我需要一根线吗?我不知道。

现在我没有打印任何东西,而函数正在执行,但一个进度条会很好。此外,我更感兴趣的是从代码的角度如何做到这一点。


当前回答

我想我有点晚了,但这应该适用于使用当前版本的python 3的人,因为这使用了“f-strings”,正如python 3.6 PEP 498中介绍的那样:

Code

from numpy import interp

class Progress:
    def __init__(self, value, end, title='Downloading',buffer=20):
        self.title = title
        #when calling in a for loop it doesn't include the last number
        self.end = end -1
        self.buffer = buffer
        self.value = value
        self.progress()

    def progress(self):
        maped = int(interp(self.value, [0, self.end], [0, self.buffer]))
        print(f'{self.title}: [{"#"*maped}{"-"*(self.buffer - maped)}]{self.value}/{self.end} {((self.value/self.end)*100):.2f}%', end='\r')

例子

#some loop that does perfroms a task
for x in range(21)  #set to 21 to include until 20
    Progress(x, 21)

输出

Downloading: [########------------] 8/20 40.00%

其他回答

上面的建议非常好,但我认为大多数人只是想要一个现成的解决方案,不依赖于外部包,但也是可重用的。

我得到了上面所有的优点,并把它做成了一个函数,以及一个测试用例。

要使用它,只需复制“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

试试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

已经有很多好的答案,但添加这个特定的基于@HandyGold75的答案,我希望它在特定的上下文中是callabe,有一个初始的msg,加上在结束时的几秒钟的时间反馈。

from time import sleep, time


class ProgressBar:
    def __init__(self, total: float, width: int = 50, msg: str = ""):
    self.total = total
    self.width = width
    self.start: float = time()
    if msg:
        print(f"{msg}")

    def progress(self, progress: float):
        percent = self.width * ((progress) / self.total)
        bar = chr(9608) * int(percent) + "-" * (self.width - int(percent))
        print(
            f"\r|{bar}| {(100/self.width)*percent:.2f}% "
            f"[{progress} of {self.total}]",
            end="\r",
        )

    def __enter__(self):
        return self.progress

    def __exit__(self, type, value, traceback):
        end: float = time()
        print(f"\nFinished after {end - self.start: .3f} seconds.")


# USAGE
total_loops = 150
with ProgressBar(total=total_loops) as progress:
    for i in range(total_loops):
        sleep(0.01)  # Do something usefull here
        progress(i + 1)

这里有一个非常简单的版本,如果你有一个循环,只是想了解迭代的进展,比如每一个点,比如说,5000次迭代。

my_list = range(0,100000)

counter = 0
for x in my_list:
    #your code here

    counter = counter + 1
    if counter % 5000 == 0:
        print(".", end="") # end="" avoids a newline, keeps dots together

print() #this makes sure whatever you print next is in a new line

My_list不是方案的一部分。使用你自己的迭代对象,不管你在循环什么。 这个版本没有提前告诉您总共有多少次迭代。

你可以使用tqdm:

from tqdm import tqdm

with tqdm(total=100, desc="Adding Users", bar_format="{l_bar}{bar} [ time left: {remaining} ]") as pbar:
    for i in range(100):
        time.sleep(3)
        pbar.update(1)

在本例中,进度条运行了5分钟 它是这样显示的:

Adding Users:   3%|█████▊                                     [ time left: 04:51 ]                                                                                                        

您可以随心所欲地更改它和自定义它。