[python] 控制台中的文本進度欄



13 Answers

寫'\ r'會將光標移回行的開頭。

這顯示一個百分比計數器:

import time
import sys

for i in range(100):
    time.sleep(1)
    sys.stdout.write("\r%d%%" % i)
    sys.stdout.flush()
Question

有沒有一種好辦法來做到以下幾點?

我編寫了一個簡單的控制台應用程序,使用ftplib從FTP服務器上載和下載文件。

每次下載一些數據塊時,我都想更新文本進度條,即使它只是一個數字。

但我不想刪除所有打印到控制台的文本。 (做一個“清除”,然後打印更新的百分比。)




我正在使用reddit的進度 。 我喜歡它,因為它可以在一行中打印每個項目的進度,並且它不應該從程序中清除打印輸出。

編輯:固定鏈接







python模塊進度條是一個不錯的選擇。 這是我的典型代碼:

import time
import progressbar

widgets = [
    ' ', progressbar.Percentage(),
    ' ', progressbar.SimpleProgress(format='(%(value_s)s of %(max_value_s)s)'),
    ' ', progressbar.Bar('>', fill='.'),
    ' ', progressbar.ETA(format_finished='- %(seconds)s  -', format='ETA: %(seconds)s', ),
    ' - ', progressbar.DynamicMessage('loss'),
    ' - ', progressbar.DynamicMessage('error'),
    '                          '
]

bar = progressbar.ProgressBar(redirect_stdout=True, widgets=widgets)
bar.start(100)
for i in range(100):
    time.sleep(0.1)
    bar.update(i + 1, loss=i / 100., error=i)
bar.finish()



import time,sys

for i in range(100+1):
    time.sleep(0.1)
    sys.stdout.write(('='*i)+(''*(100-i))+("\r [ %d"%i+"% ] "))
    sys.stdout.flush()

產量

[29%] ===================




我寫了一個簡單的進度條:

def bar(total, current, length=10, prefix="", filler="#", space=" ", oncomp="", border="[]", suffix=""):
    if len(border) != 2:
        print("parameter 'border' must include exactly 2 symbols!")
        return None

    print(prefix + border[0] + (filler * int(current / total * length) +
                                      (space * (length - int(current / total * length)))) + border[1], suffix, "\r", end="")
    if total == current:
        if oncomp:
            print(prefix + border[0] + space * int(((length - len(oncomp)) / 2)) +
                  oncomp + space * int(((length - len(oncomp)) / 2)) + border[1], suffix)
        if not oncomp:
            print(prefix + border[0] + (filler * int(current / total * length) +
                                        (space * (length - int(current / total * length)))) + border[1], suffix)

正如你所看到的,它具有:條的長度,前綴和後綴,填充符,空格,100%(oncomp)和邊框上的文本

這裡是一個例子:

from time import sleep, time
start_time = time()
for i in range(10):
    pref = str((i+1) * 10) + "% "
    complete_text = "done in %s sec" % str(round(time() - start_time))
    sleep(1)
    bar(10, i + 1, length=20, prefix=pref, oncomp=complete_text)

正在進行中:

30% [######              ]

完整:

100% [   done in 9 sec   ] 



這是我的Python 3解決方案:

import time
for i in range(100):
    time.sleep(1)
    s = "{}% Complete".format(i)
    print(s,end=len(s) * '\b')

'\ b'是反斜杠,用於字符串中的每個字符。 這在Windows cmd窗口中不起作用。




把我在這裡找到的一些想法放在一起,並增加估計的時間:

import datetime, sys

start = datetime.datetime.now()

def print_progress_bar (iteration, total):

    process_duration_samples = []
    average_samples = 5

    end = datetime.datetime.now()

    process_duration = end - start

    if len(process_duration_samples) == 0:
        process_duration_samples = [process_duration] * average_samples

    process_duration_samples = process_duration_samples[1:average_samples-1] + [process_duration]
    average_process_duration = sum(process_duration_samples, datetime.timedelta()) / len(process_duration_samples)
    remaining_steps = total - iteration
    remaining_time_estimation = remaining_steps * average_process_duration

    bars_string = int(float(iteration) / float(total) * 20.)
    sys.stdout.write(
        "\r[%-20s] %d%% (%s/%s) Estimated time left: %s" % (
            '='*bars_string, float(iteration) / float(total) * 100,
            iteration,
            total,
            remaining_time_estimation
        ) 
    )
    sys.stdout.flush()
    if iteration + 1 == total:
        print 


# Sample usage

for i in range(0,300):
    print_progress_bar(i, 300)



根據上面的回答和其他有關CLI進度條的類似問題,我想我對所有人都有一個普遍的答案。 檢查它在https://.com/a/15860757/2254146

總之,代碼是這樣的:

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

好像

百分比:[##########] 99.0%




檢查這個庫: clint

它有很多功能,包括進度條:

from time import sleep  
from random import random  
from clint.textui import progress  
if __name__ == '__main__':
    for i in progress.bar(range(100)):
        sleep(random() * 0.2)

    for i in progress.dots(range(100)):
        sleep(random() * 0.2)

link提供了其功能的快速概述




嘗試使用由Mozart of Python,Armin Ronacher編寫的click庫。

$ pip install click # both 2 and 3 compatible

創建一個簡單的進度條:

import click

with click.progressbar(range(1000000)) as bar:
    for i in bar:
        pass 

這是它的樣子:

# [###-------------------------------]    9%  00:01:14

定制你心中的內容:

import click, sys

with click.progressbar(range(100000), file=sys.stderr, show_pos=True, width=70, bar_template='(_(_)=%(bar)sD(_(_| %(info)s', fill_char='=', empty_char=' ') as bar:
    for i in bar:
        pass

自定義外觀:

(_(_)===================================D(_(_| 100000/100000 00:00:02

還有更多選項,請參閱API文檔

 click.progressbar(iterable=None, length=None, label=None, show_eta=True, show_percent=None, show_pos=False, item_show_func=None, fill_char='#', empty_char='-', bar_template='%(label)s [%(bar)s] %(info)s', info_sep=' ', width=36, file=None, color=None)



有了上面的偉大建議,我可以找出進度條。

不過,我想指出一些缺點

  1. 每當進度條被刷新時,它都會以新行開始

    print('\r[{0}]{1}%'.format('#' * progress* 10, progress))  
    

    喜歡這個:
    [] 0%
    [#] 10%
    [##] 20%
    [###] 30%

2.方括號']'和右側的百分數右移,'###'變長。
3.如果表達式'progress / 10'不能返回整數,則會發生錯誤。

以下代碼將解決上述問題。

def update_progress(progress, total):  
    print('\r[{0:10}]{1:>2}%'.format('#' * int(progress * 10 /total), progress), end='')



在Python命令行中運行( 不在任何IDE或開發環境中):

>>> import threading
>>> for i in range(50+1):
...   threading._sleep(0.5)
...   print "\r%3d" % i, ('='*i)+('-'*(50-i)),

在我的Windows系統上正常工作。




import sys
def progresssbar():
         for i in range(100):
            time.sleep(1)
            sys.stdout.write("%i\r" % i)

progressbar()

注意:如果您在交互式聯機程序中運行此功能,則會打印出額外的數字






Related