Python 进度条

Posted

技术标签:

【中文标题】Python 进度条【英文标题】:Python Progress Bar 【发布时间】:2011-03-10 19:06:13 【问题描述】:

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

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

请注意,我需要它是实时的,所以我不知道该怎么做。我需要thread吗?我不知道。

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

【问题讨论】:

您使用的是 GUI 工具包还是仅 CLI? CLI。但是我可以使用第三方库,这没问题。使用 GUI 我可以做到这一点,但我对 CLI 部分很感兴趣。 Text Progress Bar in the Console 的可能重复项请注意,虽然此问题是在三天前发布的,但链接问题的查看频率更高。 这里是 Jupyter Notebook 内的解决方案:mikulskibartosz.name/… 我发布了一种新的进度条,除了非常酷的动画外,您还可以打印、查看吞吐量和 eta,甚至暂停它!请看:github.com/rsalmei/alive-progress!alive-progress 【参考方案1】:

使用alive-progress,有史以来最酷的进度条!

要以有用的方式使用任何进度条框架,即获得完成百分比和预计到达时间 (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 的文档以了解更多信息。现在它也适用于 Jupyter Notebooks!以下是它可以做的更多示例:

【讨论】:

这确实是我在 *** 上见过的最好的。 这太酷了,我不是典型的崇拜者,但这个库很棒。干得好兄弟 非常流畅且易于使用。 爱它! jupyter notebook 支持怎么样了? 最佳示例:GIF alive-progress【参考方案2】:

2022 无外部库的简单进度条答案

import time, sys

def progress(size):
    for item in range(size):
        if(item==0):
            print("[",end="")

        elif(item==size-1):
            print("]",end="\n")

        else:
            #main work goes here
            time.sleep(0.1)
            print("%",end="")
            sys.stdout.flush()

progress(50)

【讨论】:

【参考方案3】:

这个答案不依赖外部包,我也认为大多数人只想要一段现成的代码。下面的代码可以通过自定义来适应您的需求:进度条符号'#'、条形图size、文本prefix等。

import sys

def progressbar(it, prefix="", size=60, file=sys.stdout):
    count = len(it)
    def show(j):
        x = int(size*j/count)
        file.write("%s[%s%s] %i/%i\r" % (prefix, "#"*x, "."*(size-x), j, count))
        file.flush()        
    show(0)
    for i, item in enumerate(it):
        yield item
        show(i+1)
    file.write("\n")
    file.flush()

用法:

import time

for i in progressbar(range(15), "Computing: ", 40):
    time.sleep(0.1) # any calculation you need

输出:

不需要第二个线程。上面的一些解决方案/包需要。

适用于任何可迭代对象,这意味着可以使用 len() 的任何东西。一个list,一个dict,例如['a', 'b', 'c' ... 'g']

与生成器一起工作只需要用 list() 包装它。例如for i in progressbar(list(your_generator), "Computing: ", 40): 除非工作是在生成器中完成的。在这种情况下,您需要另一种解决方案(例如 tqdm)

例如,您也可以通过将文件更改为sys.stderr 来更改输出

【讨论】:

我喜欢这个解决方案,生成器会抛出以下错误:TypeError: object of type 'generator' has no len() 之前应该看过这个评论,浪费时间弄清楚如何让它与生成器一起工作。我必须说转换为列表可能对大对象没有帮助,因为生成器的点丢失了。 (就我而言,我正在阅读 PDF 中的页面,我不想将所有页面都加载到内存中)。我很欣赏添加进度条库的简单性 这是迄今为止最干净的解决方案 将生成器包装为列表似乎确实没有抓住重点。如果所有工作都在生成器中完成,那么进度条将不会显示进度。 (例如,tqdm 会处理这个问题,除非你告诉它总数,否则不会显示百分比)关于线程问题的评论可能不是 100% 准确的。 jupyter notebook 不会有第二个线程的问题。写入两个单独的输出是(stdout 和 stderr)。 我制作了一个“更好”的版本,它将# 字符替换为填充整个字符空间的unicode 字符-。这是我提出的要点:gist.github.com/ChesterChowWOV/2b35c551b339adbf459363322aac5b4b【参考方案4】:

使用tqdm(conda install tqdmpip install tqdm),您可以在一秒钟内为循环添加进度表:

from time import sleep
from tqdm import tqdm
for i in tqdm(range(10)):
    sleep(3)

 60%|██████    | 6/10 [00:18<00:12,  0.33 it/s]

另外,还有一个notebook version:

from tqdm.notebook import tqdm
for i in tqdm(range(100)):
    sleep(3)

您可以使用tqdm.auto 代替tqdm.notebook 在终端和笔记本电脑中工作。

tqdm.contrib 包含一些辅助函数来执行enumeratemapzip 等操作。 tqdm.contrib.concurrent中有并发地图。

您甚至可以在使用tqdm.contrib.telegramtqdm.contrib.discord 与jupyter notebook 断开连接后将进度发送到您的手机。

【讨论】:

这是我发现的与终端、qtconsole 和笔记本一起使用的唯一解决方案 它是否适用于任何可迭代对象?我无法让它与字符串列表一起使用。 @JoshUsre 是的,它应该适用于任何可迭代对象,目前我没有看到任何可迭代对象阻塞。但是,ETA(剩余时间)的显示需要迭代器具有__len__ 属性,或者用户必须将total 参数提供给tqdm。否则,酒吧将工作,但没有 ETA。 @gaborous:为什么这不是投票最多的答案?与最佳答案不同,这个简单的解决方案在终端和 Jupyter 笔记本中都适用。 在 jupyter notebook 中运行使用from tqdm import tqdm_notebook as tqdm。否则不写一行。【参考方案5】:

这是一个以编程方式构建加载栏的简短解决方案(您必须决定需要多长时间)。

import time

n = 33  # or however many loading slots you want to have
load = 0.01  # artificial loading time!
loading = '.' * n  # for strings, * is the repeat operator

for i in range(n+1):
    # this loop replaces each dot with a hash!
    print('\r%s Loading at %3d percent!' % (loading, i*100/n), end='')
    loading = loading[:i] + '#' + loading[i+1:]
    time.sleep(load)
    if i==n: print()

【讨论】:

最简单的解决方案【参考方案6】:

一个简单的oneliner:

K = 628318
for k in range(K):
    # your stuff
    print(end="\r" + " "*81 + "|\r|" + "="*int(80*k/(K-1)))
|=====================================================================       |

80 是条的长度。最终你想要一个最终的print("|")

不要忘记数字进度指示器:

K = 628318
for k in range(K):
    # your stuff
    print(end="\r%6.2f %%" % (k/(K-1)*100))
 94.53 %

如果需要,将两者结合起来并不难。

关键是“回车”\rprint 中默认end="\n" 的抑制。

【讨论】:

【参考方案7】:
from IPython.display import clear_output
progress_bar=u"\u001b[7m Loading: "
for i in range(100):
    clear_output(wait=True)
    progress_bar+=u"\u001b[7m "
    print(progress_bar+str(i+1)+"%")
    time.sleep(0.03) #you can change the speed

output

【讨论】:

【参考方案8】:

iterrows 的进度条。 @eubrasileiro 代码的改编,用于在循环遍历数据帧的行时显示进度。此外还显示百分比、第 i 个/计数、经过的秒数、迭代次数/秒、剩余秒数。允许指定第 n 个更新计数(每)。

import time
import sys
def progressbar_iterrows(df, prefix="", size=60, file=sys.stdout, per=1000):
    count = len(df)
    t = 0
    def show(j,elapsed):
        avg = 0 if elapsed == 0 else j/elapsed
        remaining = 0 if avg == 0 else (count-j)/avg
        x = int(size*j/count)
        file.write("%s[%s%s] %i%% %i/%i elapsed:%i %i/sec remaining:%i\r" % (prefix, "#"*x, "."*(size-x), j/count, j, count, elapsed, avg, remaining))
        file.flush()
    file.write("Initializing ...\r")
    file.flush()
    for i, item in df.iterrows():
        yield i,item
        if t == 0:
            t = time.time()
        if i % per == 0:
            show(i,time.time()-t)
    file.write("\n")
    file.flush()

用法:

    for n,r in progressbar_iterrows(br_b_sections_df, "Processed: "):
        # do something

输出:

Processed: [........................] 0% 5000/28751240 elapsed:12 413/sec remaining:55054

【讨论】:

【参考方案9】:

我使用 wget,如果在 mac 或 linux 上,您必须在 windows 或终端的 cmd 提示符下安装模块

pip install wget

这很简单,只需使用 download() 函数

import wget
url = input("Enter Url to download: ")
wget.download(url)

tqdm 也是一个选项,你也必须下载模块。

pip install tqdm

现在确保导入模块,设置范围并通过

from tqdm import tqdm
for i in tqdm(range(int(9e7))):
    pass

【讨论】:

这个也很好!【参考方案10】:

这是一个非常简单的版本,以防您有一个循环并且只想了解迭代的进展情况,例如每 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 不是该计划的一部分。使用您自己的可迭代对象,无论您要循环什么。 此版本不会提前告诉您总迭代次数。

【讨论】:

【参考方案11】:

一个非常简单的方法:

def progbar(count: int) -> None:
    for i in range(count):
        print(f"[i*'#'(count-1-i)*' '] - i+1/count", end="\r")
        yield i
    print('\n')

及用法:

from time import sleep

for i in progbar(10):
    sleep(0.2) #whatever task you need to do

【讨论】:

这是现代 python 的一个很好的解决方案,具有类型提示、f-strings 和无导入(在实际使用中)。我的最爱!【参考方案12】:

这里有一个简单的解决方案!

void = '-'
fill = '#'
count = 100/length
increaseCount = 0
for i in range(length):
    print('['+(fill*i)+(void*(length-i))+'] '+str(int(increaseCount))+'%',end='\r')
    increaseCount += count
    time.sleep(0.1)
print('['+(fill*(i+1))+(void*(length-(i+1)))+'] '+str(int(increaseCount))+'%',end='\n')

注意:您可以根据需要修改填充和“空”字符。

The loading bar (picture)

【讨论】:

【参考方案13】:

下面的代码是一个非常通用的解决方案,并且还有一个经过时间和剩余时间的估计。您可以使用任何可迭代对象。进度条的大小固定为 25 个字符,但它可以使用完整、半和四分之一块字符以 1% 的步长显示更新。输出如下所示:

 18% |████▌                    | \ [0:00:01, 0:00:06]

示例代码:

import sys, time
from numpy import linspace

def ProgressBar(iterObj):
  def SecToStr(sec):
    m, s = divmod(sec, 60)
    h, m = divmod(m, 60)
    return u'%d:%02d:%02d'%(h, m, s)
  L = len(iterObj)
  steps = int(x):y for x,y in zip(linspace(0, L, min(100,L), endpoint=False),
                                   linspace(0, 100, min(100,L), endpoint=False))
  qSteps = ['', u'\u258E', u'\u258C', u'\u258A'] # quarter and half block chars
  startT = time.time()
  timeStr = '   [0:00:00, -:--:--]'
  activity = [' -',' \\',' |',' /']
  for nn,item in enumerate(iterObj):
    if nn in steps:
      done = u'\u2588'*int(steps[nn]/4.0)+qSteps[int(steps[nn]%4)]
      todo = ' '*(25-len(done))
      barStr = u'%4d%% |%s%s|'%(steps[nn], done, todo)
    if nn>0:
      endT = time.time()
      timeStr = ' [%s, %s]'%(SecToStr(endT-startT),
                             SecToStr((endT-startT)*(L/float(nn)-1)))
    sys.stdout.write('\r'+barStr+activity[nn%4]+timeStr); sys.stdout.flush()
    yield item
  barStr = u'%4d%% |%s|'%(100, u'\u2588'*25)
  timeStr = '   [%s, 0:00:00]\n'%(SecToStr(time.time()-startT))
  sys.stdout.write('\r'+barStr+timeStr); sys.stdout.flush()

# Example
s = ''
for c in ProgressBar(list('Disassemble and reassemble this string')):
  time.sleep(0.2)
  s += c
print(s)

感谢您提出改进或其他 cmets 的建议。干杯!

【讨论】:

【参考方案14】:

这是我的简单解决方案:

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")

【讨论】:

【参考方案15】:

使用progress library!

pip install progress

这是我编写的一个自定义子类,用于将 ETA/Elapsed 时间格式化为可读性更好的格式:

import datetime
from progress.bar import IncrementalBar


class ProgressBar(IncrementalBar):
    '''
    My custom progress bar that:
       - Show %, count, elapsed, eta
       - Time is shown in H:M:S format
    '''

    message = 'Progress'
    suffix  = '%(percent).1f%% (%(index)d/%(max)d) -- %(elapsed_min)s (eta: %(eta_min)s)'

    def formatTime(self, seconds):
        return str(datetime.timedelta(seconds=seconds))

    @property
    def elapsed_min(self):
        return self.formatTime(self.elapsed)

    @property
    def eta_min(self):
        return self.formatTime(self.eta)

if __name__=='__main__':
    counter = 120
    bar     = ProgressBar('Processing', max=counter)

    for i in range(counter):
        bar.next()
        time.sleep(1)

    bar.finish()

【讨论】:

【参考方案16】:

上面的建议都不错,但我想大多数人只是想要一个现成的解决方案,不依赖外部包,而且可以重复使用。

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

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

【讨论】:

动画测试(最后一个)应该是 in range(101) 而不是 100,进度停止在 99% 并且永远不会显示完成。 这是一个很好的答案!两个建议:1)您可以使用print(..., end='') 而不是调用stdout.write() + stdout.flush()。 2) 如果您将\r 放在字符串的末尾而不是开头,它与其他控制台输出的效果会更好。 如何让进度条在每次更新时都被覆盖,而不是每次都在控制台中添加新行? @user5359531 试试下面的答案【参考方案17】:

我使用format() 方法制作了一个负载条。这是我的解决方案:

import time

loadbarwidth = 23

for i in range(1, loadbarwidth + 1):
    time.sleep(0.1) 

    strbarwidth = '[] - \r'.format(
        (i * '#'),
        ((loadbarwidth - i) * '-'),
        ((':0.2f'.format(((i) * (100/loadbarwidth))) + '%'))
    )

    print(strbarwidth ,end = '')

print()

输出:

[#######################] - 100.00%

【讨论】:

【参考方案18】:

使用os_sys 库:

我将它用于多种类型的酒吧,例如:

from os_sys.progress import bar as Bar
bar = Bar('progresing: ', max=20)
for i in range(20):
    #do somthing
    bar.next()
bar.finish()

您的输出将是:

procesing:  |######                          | 2/10

阅读更多关于 os_sys 的说明

【讨论】:

【参考方案19】:

此进度条显示每完成 2% 的分数和每完成 10% 的数字。

import sys

def ProgressBar (num, total, nextPercent, nextPoint):
    num = float (num)
    total = float (total) - 1
    if not nextPoint:
        nextPoint = 0.0
    if not nextPercent:
        nextPoint += 2.0
        sys.stdout.write ("[0%")
        nextPercent = 10
    elif num == total:
        sys.stdout.write ("100%]\n")
        nextPercent += 10
    elif not nextPoint:
        nextPoint = 0.0
    elif num / total * 100 >= nextPercent:
        sys.stdout.write (str(int (nextPercent)) + "%")
        nextPercent += 10
    elif num / total * 100 >= nextPoint:
        sys.stdout.write (":")
        nextPoint += 2
    return (nextPercent, nextPoint)

nextPercent, nextPoint = 0, 0
total = 1000

for num in range (total):
    nextPercent, nextPoint = ProgressBar (num, total, nextPercent, nextPoint)

结果:

>>> 
[0%::::10%:::::20%:::::30%:::::40%:::::50%:::::60%:::::70%:::::80%:::::90%:::::100%]
>>> 

【讨论】:

【参考方案20】:

有一些特定的库 (like this one here),但也许一些非常简单的方法可以做到:

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 xrange(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 的一个分支,多年未维护。

【讨论】:

这不会扩展到很多步骤...pypi.python.org/pypi/progress 更容易使用 我试过这段代码,它抛出了一个NameError: name 'xrange' is not defined 错误。我错过了一个模块吗? @GokuMcSpock9733 您使用的是哪个版本的 Python? Python 的 2 xrange 是 Python 的 3 range 这不应该是最佳答案。另一个答案(使用 tqdm)至少对我来说要好得多。 Python 3 中穷人的进度条:print('■', end='', flush=True)【参考方案21】:

你可以使用tqdm:

from tqdm import tqdm

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

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

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

您可以随意更改和自定义。

【讨论】:

【参考方案22】:

这是创建进度条的简单方法

import time,sys
toolbar_width = 50
# setting up toolbar [-------------------------------------]
sys.stdout.write("[%s]"%(("-")*toolbar_width))
sys.stdout.flush()
# each hash represents 2 % of the progress
for i in range(toolbar_width):
    sys.stdout.write("\r") # return to start of line
    sys.stdout.flush()
    sys.stdout.write("[")#Overwrite over the existing text from the start 
    sys.stdout.write("#"*(i+1))# number of # denotes the progress completed 
    sys.stdout.flush()
    time.sleep(0.1)

【讨论】:

【参考方案23】:

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

代码

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%

【讨论】:

【参考方案24】:

jelde015 的更通用的答案(当然归功于他)

对于更新加载栏手动将是:

import sys
from math import *


def loadingBar(i, N, size):
    percent = float(i) / float(N)
    sys.stdout.write("\r"
                     + str(int(i)).rjust(3, '0')
                     +"/"
                     +str(int(N)).rjust(3, '0')
                     + ' ['
                     + '='*ceil(percent*size)
                     + ' '*floor((1-percent)*size)
                     + ']')

并通过以下方式调用它:

loadingBar(7, 220, 40)

结果:

007/220 [=                                       ]  

只要你想用当前的i 值调用它。

size 设置为条形应为的字符数

【讨论】:

【参考方案25】:

在 jupyter 笔记本中运行时,使用普通的 tqdm 不起作用,因为它将输出写入多行。改用这个:

import time
from tqdm import tqdm_notebook as tqdm

for i in tqdm(range(100))
    time.sleep(0.5)

【讨论】:

【参考方案26】:

如果它是一个具有固定迭代次数的大循环,需要花费大量时间,您可以使用我制作的这个函数。循环的每次迭代都会增加进度。其中 count 是循环的当前迭代,total 是您要循环到的值, size(int) 是您希望条形以 10 为增量的大小,即(大小 1 =10 个字符,大小 2 =20 个字符)

import sys
def loadingBar(count,total,size):
    percent = float(count)/float(total)*100
    sys.stdout.write("\r" + str(int(count)).rjust(3,'0')+"/"+str(int(total)).rjust(3,'0') + ' [' + '='*int(percent/10)*size + ' '*(10-int(percent/10))*size + ']')

示例:

for i in range(0,100):
     loadingBar(i,100,2)
     #do some code 

输出:

i = 50
>> 050/100 [==========          ]

【讨论】:

【参考方案27】:

在此处搜索等效解决方案后,我刚刚为我的需要制作了一个简单的进度类。我想我可能会发布它。

from __future__ import print_function
import sys
import re


class ProgressBar(object):
    DEFAULT = 'Progress: %(bar)s %(percent)3d%%'
    FULL = '%(bar)s %(current)d/%(total)d (%(percent)3d%%) %(remaining)d to go'

    def __init__(self, total, width=40, fmt=DEFAULT, symbol='=',
                 output=sys.stderr):
        assert len(symbol) == 1

        self.total = total
        self.width = width
        self.symbol = symbol
        self.output = output
        self.fmt = re.sub(r'(?P<name>%\(.+?\))d',
            r'\g<name>%dd' % len(str(total)), fmt)

        self.current = 0

    def __call__(self):
        percent = self.current / float(self.total)
        size = int(self.width * percent)
        remaining = self.total - self.current
        bar = '[' + self.symbol * size + ' ' * (self.width - size) + ']'

        args = 
            'total': self.total,
            'bar': bar,
            'current': self.current,
            'percent': percent * 100,
            'remaining': remaining
        
        print('\r' + self.fmt % args, file=self.output, end='')

    def done(self):
        self.current = self.total
        self()
        print('', file=self.output)

例子:

from time import sleep

progress = ProgressBar(80, fmt=ProgressBar.FULL)

for x in xrange(progress.total):
    progress.current += 1
    progress()
    sleep(0.1)
progress.done()

将打印以下内容:

[======== ] 17/80 ( 21%) 63 to go

【讨论】:

太棒了,谢谢你。顺便说一句,您可以在__call__ 的末尾添加递增的progress.current,以进一步限制与主代码中的对象的交互。 这段代码简洁实用!谢谢!【参考方案28】:

您也可以使用enlighten。主要优点是您可以同时登录而不会覆盖进度条。

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()

【讨论】:

【参考方案29】:

在 Python3 中非常简单:

   import time
   import math

    def show_progress_bar(bar_length, completed, total):
        bar_length_unit_value = (total / bar_length)
        completed_bar_part = math.ceil(completed / bar_length_unit_value)
        progress = "*" * completed_bar_part
        remaining = " " * (bar_length - completed_bar_part)
        percent_done = "%.2f" % ((completed / total) * 100)
        print(f'[progressremaining] percent_done%', end='\r')

    bar_length = 30
    total = 100
    for i in range(0, total + 1):
        show_progress_bar(bar_length, i, total)
        time.sleep(0.1)

    print('\n')

【讨论】:

【参考方案30】:

试试 PyProg。 PyProg 是一个用于 Python 的开源库,用于创建超级可定制的进度指示器和条形图。

目前版本为 1.0.2;它托管在 Github 上并在 PyPI 上可用(链接如下)。它与 Python 3 & 2 兼容,也可以与 Qt 控制台一起使用。

它真的很容易使用。以下代码:

import pyprog
from time import sleep

# Create Object
prog = pyprog.ProgressBar(" ", "", 34)
# Update Progress Bar
prog.update()

for i in range(34):
    # Do something
    sleep(0.1)
    # Set current status
    prog.set_stat(i + 1)
    # Update Progress Bar again
    prog.update()

# Make the Progress Bar final
prog.end()

将产生:

Initial State:
Progress: 0% --------------------------------------------------

When half done:
Progress: 50% #########################-------------------------

Final State:
Progress: 100% ##################################################

我实际上制作了 PyProg,因为我需要一个简单但超级可定制的进度条库。您可以通过以下方式轻松安装它:pip install pyprog

PyProg Github:https://github.com/Bill13579/pyprog PyPI:https://pypi.python.org/pypi/pyprog/

【讨论】:

以上是关于Python 进度条的主要内容,如果未能解决你的问题,请参考以下文章

python编写文本进度条

python进度条

Python 进度条未正确显示进度

[Python] 实现文本进度条

Python开发技巧-教你制作Python进度条

python进度条