簡體   English   中英

Python 進度條

[英]Python Progress Bar

當我的腳本正在執行一些可能需要時間的任務時,如何使用進度條?

例如,一個 function 需要一些時間才能完成並在完成時返回True 如何在執行 function 期間顯示進度條?

請注意,我需要它是實時的,所以我不知道該怎么做。 我需要一個thread嗎? 我不知道。

現在在執行 function 時我沒有打印任何東西,但是進度條會很好。 此外,我對如何從代碼的角度完成此操作更感興趣。

使用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]

此外,還有一個筆記本版本

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 的連接后,您甚至可以將進度發送到您的手機。

GIF 顯示使用 tqdm.contrib.telegram 在 Telegram 移動應用程序中顯示進度條的輸出示例

有特定的庫(比如這里的這個),但也許可以做一些非常簡單的事情:

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是一個多年未維護的進度條的分支。

使用alive-progress ,有史以來最酷的進度條!

GIF 顯示了一個活着的進步的例子

要以有用的方式使用任何進度條框架,即獲得完成百分比和預計到達時間 (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! 以下是它可以做什么的更多示例:

GIF 顯示各種風格的生活進度

GIF 顯示 Jupyter Notebooks 上的實時進度

沒有外部軟件包。 一段現成的代碼。

您可以自定義欄進度符號"#" 、欄size 、文本prefix等。

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"█" char 替換"#" 隨着for i in progressbar(range(100)): ...你得到:

在此處輸入圖像描述

  • 不需要第二個線程 上面的一些解決方案/包需要。

  • 適用於任何可迭代對象,這意味着可以使用len()的任何對象。 一個list ,任何東西的dict ,例如['a', 'b', 'c' ... 'g']

  • 與生成器一起工作只需要用 list() 包裝它。 例如for i in progressbar(list(your_generator), "Computing: ", 40):除非工作是在生成器中完成的。 在這種情況下,您需要另一種解決方案(如 tqdm)

例如,您還可以通過更改為sys.stderr來更改out


Python 3.6+(f 字符串)

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(舊代碼)

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

上面的建議都不錯,但我想大多數人只是想要一個現成的解決方案,不依賴外部包,但也可以重用。

我得到了以上所有優點,並將其與測試用例一起制作成一個函數。

要使用它,只需復制“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嘗試進度。

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

對於類似的應用程序(循環跟蹤進度),我只是使用了python-progressbar

他們的例子是這樣的,

from progressbar import *               # just a simple progress bar


widgets = ['Test: ', Percentage(), ' ', Bar(marker='0',left='[',right=']'),
           ' ', ETA(), ' ', FileTransferSpeed()] #see docs for other options

pbar = ProgressBar(widgets=widgets, maxval=500)
pbar.start()

for i in range(100,500+1,50):
    # here do something long at each iteration
    pbar.update(i) #this adds a little symbol at each iteration
pbar.finish()
print

在此處搜索等效解決方案后,我剛剛為我的需要制作了一個簡單的進度類。 我想我可能會很好地發布它。

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

您可以使用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 ]                                                                                                        

您可以根據需要更改和自定義它。

我喜歡Brian Khuu 的答案,因為它簡單且不需要外部軟件包。 我改變了一點,所以我在這里添加我的版本:

import sys
import time


def updt(total, progress):
    """
    Displays or updates a console progress bar.

    Original source: https://stackoverflow.com/a/15860757/1391441
    """
    barLength, status = 20, ""
    progress = float(progress) / float(total)
    if progress >= 1.:
        progress, status = 1, "\r\n"
    block = int(round(barLength * progress))
    text = "\r[{}] {:.0f}% {}".format(
        "#" * block + "-" * (barLength - block), round(progress * 100, 0),
        status)
    sys.stdout.write(text)
    sys.stdout.flush()


runs = 300
for run_num in range(runs):
    time.sleep(.1)
    updt(runs, run_num + 1)

假設total >= progress ,它需要運行總數 ( total ) 和到目前為止處理的運行數 ( progress )。 結果如下所示:

[#####---------------] 27%

我真的很喜歡python-progressbar ,因為它使用起來非常簡單。

對於最簡單的情況,它只是:

import progressbar
import time

progress = progressbar.ProgressBar()
for i in progress(range(80)):
    time.sleep(0.01)

外觀可定制,可顯示預計剩余時間。 例如,使用與上面相同的代碼,但具有:

progress = progressbar.ProgressBar(widgets=[progressbar.Bar('=', '[', ']'), ' ',
                                            progressbar.Percentage(), ' ',
                                            progressbar.ETA()])

使用這個庫: fish ( GitHub )。

用法:

>>> import fish
>>> while churning:
...     churn_churn()
...     fish.animate()

玩得開心!

如果它是一個具有固定迭代次數的大循環,需要花費大量時間,您可以使用我制作的這個函數。 循環的每次迭代都會增加進度。 其中 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 [==========          ]

一個簡單的oneliner:

K = 628318
for k in range(K):
    # your stuff
    print(end="\r|%-80s|" % ("="*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"的抑制。

["

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

在 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'[{progress}{remaining}] {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')

在 jupyter 筆記本中運行時,使用普通 tqdm 不起作用,因為它會在多行上寫入輸出。 改用這個:

import time
from tqdm import tqdm_notebook as tqdm

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

我喜歡這個頁面

從簡單的示例開始,然后轉到多線程版本。 開箱即用。 不需要第 3 方包。

代碼將如下所示:

import time
import sys

def do_task():
    time.sleep(1)

def example_1(n):
    for i in range(n):
        do_task()
        print '\b.',
        sys.stdout.flush()
    print ' Done!'

print 'Starting ',
example_1(10)

或者這里是使用線程以在程序運行時運行旋轉加載欄的示例:

import sys
import time
import threading

class progress_bar_loading(threading.Thread):

    def run(self):
            global stop
            global kill
            print 'Loading....  ',
            sys.stdout.flush()
            i = 0
            while stop != True:
                    if (i%4) == 0: 
                        sys.stdout.write('\b/')
                    elif (i%4) == 1: 
                        sys.stdout.write('\b-')
                    elif (i%4) == 2: 
                        sys.stdout.write('\b\\')
                    elif (i%4) == 3: 
                        sys.stdout.write('\b|')

                    sys.stdout.flush()
                    time.sleep(0.2)
                    i+=1

            if kill == True: 
                print '\b\b\b\b ABORT!',
            else: 
                print '\b\b done!',


kill = False      
stop = False
p = progress_bar_loading()
p.start()

try:
    #anything you want to run. 
    time.sleep(1)
    stop = True
except KeyboardInterrupt or EOFError:
         kill = True
         stop = True

這是一個以編程方式構建加載欄的簡短解決方案(您必須決定需要多長時間)。

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

我使用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%

沒有外部庫的簡單進度條的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)

如果你的工作不能被分解成可測量的塊,你可以在一個新線程中調用你的函數並計算它需要多長時間:

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"

您顯然可以根據需要提高計時精度。

我喜歡加布里埃爾的回答,但我把它改成了靈活的。 您可以將 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%

完畢。

猜我有點晚了,但這應該適用於使用當前版本的 python 3的人,因為它使用 Python 3.6 PEP 498中介紹的“f-strings”

代碼

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%

使用進度庫

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

這是我的簡單解決方案:

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

一個非常簡單的方法:

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

試試 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
皮皮: https ://pypi.python.org/pypi/pyprog/

您也可以使用啟蒙 主要優點是您可以同時登錄而不會覆蓋進度條。

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

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設置為條形應為的字符數

我使用 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

已經有很多驚人的答案了,我想分享我對進度條的解決方案。

from time import sleep

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

numbers = range(0, 1000)
numbersLen = len(numbers)
for i in numbers:
    sleep(0.01) # Do something usefull here
    progress_bar(i, numbersLen)

編輯:

如果您正在尋找一個可以根據終端的寬度調整它的條形圖,並且最后可能會出現消息,那么這也可以。 請注意,如果終端變得太窄,則該消息將消失,因為如果它對於 1 行來說太寬,則條將中斷。

def progressBar(progress: float, total: float, message: str = ""):
    terminalWidth = get_terminal_size().columns
    width = int(terminalWidth / 4)
    percent = width * ((progress + 1) / total)
    bar = chr(9608) * int(percent) + "-" * (width - int(percent))
    if terminalWidth <= 40:
        message = ""
    else:
        message = message + (" " * (int(terminalWidth / 2) - len(message)))
    print(f"\r|{bar}| {(100/width)*percent:.2f}% " + message, end="\r")

已經有很多好的分析器了,但是根據@HandyGold75 的答案添加這個特定的,我希望它在特定的上下文中被調用,帶有初始的消息,加上最后幾秒鍾的時間反饋。

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)

@Massagran:它在我的程序中運行良好。 此外,我們需要添加一個計數器來指示循環時間。 此計數器用作方法update的參數。 例如:讀取測試文件的所有行並將它們處理為某事。 假設函數dosth()與變量i無關。

lines = open(sys.argv[1]).readlines()
i = 0
widgets=[Percentage(), Bar()]
pbar = ProgressBar(widgets=widgets,maxval=len(lines)).start()
pbar.start()
for line in lines:<pre>
    dosth();
    i += 1
    pbar.update(i)</pre>
pbar.finish()

變量i通過方法update控制pbar的狀態

您應該將進度條鏈接到手頭的任務(以便它衡量進度:D)。 例如,如果您正在通過 FTP 傳輸文件,您可以告訴 ftplib 獲取某個大小的緩沖區,比如說 128K,然后您將 128k 代表的文件大小百分比添加到進度條。 如果您使用的是 CLI,並且您的進度條有 20 個字符長,那么您將在文件傳輸 1/20 時添加一個字符。

使用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 的描述中閱讀更多內容

這是創建進度條的簡單方法

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)

此進度條顯示每完成 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%]
>>> 

這里有一個簡單的解決方案!

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

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

加載欄(圖片)

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

堆棧到博客進度 display.gif

發布的答案都沒有完全滿足我的需求。 所以我寫了我自己的,如上圖所示。 我需要的功能:

  • 只傳遞步驟數和總步驟數,它完成計算完成百分比的困難工作。
  • 僅使用 60 個字符空格,將它們分成 240 個“刻度”,以提供從 0.25% 到 100% 的更好的粒度顯示。
  • 支持添加標題。
  • 可選百分比在行尾完成。
  • 默認為 60 個字符或 240 個“刻度”的可變長度進度條。

如何調用進度顯示

調用進度顯示非常簡單。 對於上面的示例.gif ,使用以下方法調用該函數:

percent_complete(step, total_steps, title="Convert Markdown")

CSV 格式的 Stack Exchange 數據轉儲中len(rows)total_steps約為 2,500。 step是當前行號,因為每個 Stack Exchange Markdown Q&A 都被轉換為 Kramdown(用於 GitHub 頁面)。

Python代碼

代碼很簡單,但比其他答案長一點:

def percent_complete(step, total_steps, bar_width=60, title="", print_perc=True):
    import sys

    fill = "▒"                      # Fill up to bar_width
    utf_8s = ["▉", "▎", "▌", "▊"]   # UTF-8 left blocks: 7/8, 1/4, 1/2, 3/4
    perc = 100 * float(step) / float(total_steps)
    max_ticks = bar_width * 4
    num_ticks = int(round(perc / 100 * max_ticks))
    full_ticks = num_ticks / 4      # Number of full blocks
    part_ticks = num_ticks % 4      # Size of partial block (array index)

    disp = bar = ""                 # Blank out variables
    bar += utf_8s[0] * full_ticks   # Add full blocks into Progress Bar

    # If part_ticks is zero, then no partial block, else append part char
    if part_ticks > 0:
        bar += utf_8s[part_ticks]

    # Pad Progress Bar with fill character
    bar += fill * int((max_ticks/4 - float(num_ticks)/4.0))

    if len(title) > 0:
        disp = title + ": "         # Optional title to progress display

    disp += bar                     # Progress bar to progress display
    if print_perc:
        # If requested, append percentage complete to progress display
        if perc > 100.0:
            perc = 100.0            # Fix "100.04 %" rounding error
        disp += " {:6.2f}".format(perc) + " %"

    # Output to terminal repetitively over the same line using '\r'.
    sys.stdout.write("\r" + disp)
    sys.stdout.flush()

Python 代碼注釋

幾點:

  • [ .... ]括號占位符不是必需的,因為存在用於相同目的的填充字符。 這會節省兩個額外的字符,使進度條變寬。
  • bar_width關鍵字參數可以根據屏幕寬度使用。 默認值60似乎適合大多數用途。
  • 可以通過在調用函數時傳遞print_perc=False來覆蓋print_perc=True關鍵字參數默認值。 這將允許更長的進度條。
  • title=""關鍵字參數默認為無標題。 如果您希望使用title="My Title"並且:將自動添加到其中。
  • 當您的程序完成時,請記住調用sys.stdout.write("\\r")后跟sys.stdout.flush()以清除進度顯示行。

概括

這個答案比其他答案要長一些,但重要的是要注意它是一個完整的解決方案,而不是您需要添加更多代碼的解決方案的一部分。

另一點是這個解決方案沒有依賴項,也不需要安裝任何額外的東西。 Python 支持 UTF-8 字符集,不需要額外設置gnome-terminal 如果您使用的是 Python 2.7,您可能需要# -*- coding: utf-8 -*-在 shebang 之后。 IE 作為程序的第二行。

該函數可以轉換為具有單獨initupdatepause (用於將調試內容打印到屏幕)、 resumeclose方法的類。

此函數是從 bash 腳本轉換而來的。 每當電視音量發生變化時,bash 腳本都會使用libnotify-bin (彈出氣泡消息)顯示索尼電視音量。 如果您對 bash 版本感興趣,請在下面發表評論。

#doesnt affect actual execution
#based on events and consumption in background
#may be that actual process completes a bit earlier than progress shows 99%
#make an instance with number of elements in a loop
#in each iteration call the method current_progress

import time
from math import ceil
import os
import sys
from threading import Thread
class progress_bar(object):
 def __init__(self,total_elements,length_bar=25):
  self.length_bar=length_bar
  self.total_elements=total_elements
  self.singleweight=(float(1)/float(total_elements))*100
  self.done=0
  self.qt=[0]
  self.call_count=0
  t=Thread(target=self.display_progress)
  t.start()
 def current_progress(self):
  self.done+=1
  self.qt=[self.done]+self.qt
 def display_progress(self):
  while True:
   try:
    done=self.qt.pop()
   except:
    continue
   else:
    self.call_count+=1
    self.progress=self.singleweight*done
    fill=ceil(self.progress)
    bar=int((fill*self.length_bar)/100)*"|"
    bar="["+bar+str(fill)+"%"
    barp=bar
    for i in range(0,self.length_bar+3-(len(bar))):
     barp=barp+"_"
    barp=barp+"]"
    if self.progress <= 100:
     os.system("clear")
     print("Progress:",barp, sep=' ', end='\n', file=sys.stdout, flush=True)
    if self.call_count == self.total_elements:
     break
  else:
   pass

受到許多沒有 package 依賴的答案的啟發,我在這里分享我的實現。 用於任何循環的 function 需要當前迭代次數、迭代總數和初始時間。

import time    
def simple_progress_bar(i: int, n: int, init_time: float):
    avg_time = (time.time()-init_time)/(i+1)
    percent = ((i+1)/(n))*100
    print(
        end=f"\r|{'='*(int(percent))+'>'+'.'*int(100-int(percent))}|| " + \
        f"||Completion: {percent : 4.3f}% || \t "+ \
        f"||Time elapsed: {avg_time*(i+1):4.3f} seconds || \t " + \
        f"||Remaining time: {(avg_time*(n-(i+1))): 4.3f} seconds."
    )
    return



N = 325
t0 = time.time()
for k in range(N):
    # stuff goes here #
    time.sleep(0.0001)
    # stuff goes here #
    
    simple_progress_bar(k, N, t0)

pip install progressbar2

進度條 進度條 進度條 進度條 進度條

import os
import time
import progressbar 

os.environ['PYCHARM_HOSTED'] = '1' # https://github.com/WoLpH/python-progressbar/issues/237

class COLOR: # https://stackoverflow.com/a/287944/11465149
    YELLOW    = '\033[93m'
    GREEN     = '\033[92m'
    RED       = '\033[91m'
    BOLD      = '\033[1m'
    ENDC      = '\033[0m'

widgets=[
    'FILE.JSON ',
    COLOR.YELLOW          , progressbar.Percentage()                        , COLOR.ENDC,
    COLOR.RED + COLOR.BOLD, progressbar.Bar(left=' ', marker='━', right=' '), COLOR.ENDC,
    COLOR.YELLOW          , progressbar.Timer()                             , COLOR.ENDC
]

for i in progressbar.progressbar(range(100), widgets=widgets):
    time.sleep(0.01)
    if i == 99:
        widgets[4] = COLOR.GREEN

使用enumerate(...progressbar(max_value=...) + this如果您想將其用作下載進度條

您可以使用豐富的庫,它具有非常好的終端樣式,包括進度條。 首先運行以下命令: pip install rich

來自文檔的示例:

import time
from rich.progress import track

for i in track(range(20), description="Processing..."):
    time.sleep(1)  # Simulate work being done

這是一個非常簡單的版本,以防您有一個循環並且只想了解迭代的進展情況,例如每 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 不是該計划的一部分。 使用您自己的可迭代對象,無論您在循環什么。 此版本不會提前告訴您總迭代次數。

想擁有最小最少的線條,

for i in range(1,10):
 print("Progress: "+i*"#" , end="\r")
 time.sleep(1)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM