ステータスバーとパーセンテージを出力するPython


160

以下のようなステータスバーを実装するには:

[==========                ]  45%
[================          ]  60%
[==========================] 100%

これをstdoutに出力し、別の行に出力するのではなく、更新し続けたいです。これを行う方法?


新しい種類のプログレスバーを公開しました。これを使用すると、非常にクールなアニメーションの他に、印刷してスループットやエータを確認したり、一時停止することさえできます。ご覧ください:github.com/rsalmei/alive-progressalive-progress
rsalmei

回答:


146

Pythonモジュールは、あなたから得ることができることがありますは、PyPIと呼ばれるprogressbar道具ような機能ということ。依存関係を追加することを気にしない場合、それは良い解決策です。それ以外の場合は、他の答えのいずれかを使用してください。

使い方の簡単な例:

import progressbar
from time import sleep
bar = progressbar.ProgressBar(maxval=20, \
    widgets=[progressbar.Bar('=', '[', ']'), ' ', progressbar.Percentage()])
bar.start()
for i in xrange(20):
    bar.update(i+1)
    sleep(0.1)
bar.finish()

これをインストールするには、を使用するeasy_install progressbarpip install progressbar、pipを使用します。


すべての答えは素晴らしいですが、私はモジュールが一番好きです。皆に感謝します。
Stan

8
おそらく、この例には次のようなものが必要bar.start()ですか?
ジムレイナー、2015年

2
私のマシンでは動作しませんbar.start()
Zach

1
このモジュールは2年以上更新されていません。新しいソフトウェアには使用しないでください。
Navin 2017

4
インストール:sudo -H pip install progressbar2
マーティントーマ2017

254

'\r'文字(キャリッジリターン)は、行の先頭にカーソルをリセットし、あなたがライン上で以前にあったものを上書きすることができます。

from time import sleep
import sys

for i in range(21):
    sys.stdout.write('\r')
    # the exact output you're looking for:
    sys.stdout.write("[%-20s] %d%%" % ('='*i, 5*i))
    sys.stdout.flush()
    sleep(0.25)

これがすべてのシステムで完全に移植可能かどうかは100%わかりませんが、少なくともLinuxとOSXで動作します。


7
これはPython 3でも機能するため、マークされた回答よりも優れています。
ゲルハルトハゲラー16年

書き込まれている文字列をnullで終了しても、行の終わりに奇妙な文字が表示されることがあるのはなぜですか?
タンク

23
書かれているように、コードはこれを反復するサイズ(21ではない)にこれをどのように適応させるかを明確にしていません。私は聞かせn=21、交換するrange(21)range(n)、その後、追加j = (i + 1) / nループ内、および交換するwriteこのわずかな変更で声明を:sys.stdout.write("[%-20s] %d%%" % ('='*int(20*j), 100*j))。ここで行う必要がある唯一の変更はn=21、ループの前に(より可能性が高いn=len(iterable))、次に反復可能オブジェクトを列挙することです。この編集を推奨しましたが、拒否されました。明らかに機能性は「投稿の本来の意図から逸脱している」。
スティーブンC.ハウエル

1
n sys.stdout.write("[{:{}}] {:.1f}%".format("="*i, n-1, (100/(n-1)*i)))
、、

3
@ StevenC.Howellなぜマークを引用して回答として投稿しないのですか?それは別のバージョンであり、それを準備することは非常に役立ちます
GM

91

私は有用なライブラリtqdmを見つけました(https://github.com/tqdm/tqdm/、以前はhttps://github.com/noamraph/tqdm)。完了時間を自動的に推定し、反復子として使用できます。

使用法:

import tqdm
import time

for i in tqdm.tqdm(range(1000)):
    time.sleep(0.01)
    # or other long operations

結果:

|####------| 450/1000  45% [elapsed: 00:04 left: 00:05, 99.15 iters/sec]

tqdm イテラブルをラップできます。


4
現在、tqdmプロジェクトは、開発者の新しいチームによってここで維持されています。
15

1
わぁ、このtqdmはすごいし、とても使いやすい:)。
Sidahmed、2016

6
これは最も簡単なソリューションです
kd88 '26

2
Anaconda distribにもバンドルされています。(少なくともpython 3.5以降と同様)
Jacquot

ありがとう、
素晴らしく

23

\rキャリッジリターン)がご利用いただけます。デモ:

import sys
total = 10000000
point = total / 100
increment = total / 20
for i in xrange(total):
    if(i % (5 * point) == 0):
        sys.stdout.write("\r[" + "=" * (i / increment) +  " " * ((total - i)/ increment) + "]" +  str(i / point) + "%")
        sys.stdout.flush()

totalとして試してみると10、エラーメッセージが表示されますZeroDivisionError: long division or modulo by zero
unseen_rider

19

ここでは、次のコードを関数として使用できます。

def drawProgressBar(percent, barLen = 20):
    sys.stdout.write("\r")
    progress = ""
    for i in range(barLen):
        if i < int(barLen * percent):
            progress += "="
        else:
            progress += " "
    sys.stdout.write("[ %s ] %.2f%%" % (progress, percent * 100))
    sys.stdout.flush()

.formatを使用して:

def drawProgressBar(percent, barLen = 20):
    # percent float from 0 to 1. 
    sys.stdout.write("\r")
    sys.stdout.write("[{:<{}}] {:.0f}%".format("=" * int(barLen * percent), barLen, percent * 100))
    sys.stdout.flush()

私にとって、最初の行はカーソルによって修正されません-2行目だけが修正されます。したがって、プログレスバー用に取得された複数の行と、たとえば1つ] percent * 100 %
unseen_rider

6

上記の回答とCLIプログレスバーに関する他の同様の質問に基づいて、私はそれらすべてに一般的な一般的な回答を得たと思います。https://stackoverflow.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 = 20 # 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%


進行状況バーが表示されない
unseen_rider '15年

私はそれが多くの小数点以下の桁数がラウンドすなわちことを必要としないと思います(進捗状況を* 100,2)
アンドレス・サンチェス

4

コマンドラインインターフェイスを開発している場合は、clickどれが非常に優れているかを確認することをお勧めします。

import click
import time

for filename in range(3):
    with click.progressbar(range(100), fill_char='=', empty_char=' ') as bar:
        for user in bar:
            time.sleep(0.01)

ここであなたが得る出力:

$ python test.py
  [====================================]  100%
  [====================================]  100%
  [=========                           ]   27%

4

関数を次のように使用してさらに改善します:

import sys

def printProgressBar(i,max,postText):
    n_bar =10 #size of progress bar
    j= i/max
    sys.stdout.write('\r')
    sys.stdout.write(f"[{'=' * int(n_bar * j):{n_bar}s}] {int(100 * j)}%  {postText}")
    sys.stdout.flush()

呼び出し例:

total=33
for i in range(total):
    printProgressBar(i,total,"blah")
    sleep(0.05)  

出力:

[================================================  ] 96%  blah  

完璧!モジュールは不要
yurividal

3

私は今日このスレッドに出くわし、マーク・ルシャコフからこの解決策を試した後

from time import sleep
import sys

for i in range(21):
sys.stdout.write('\r')
# the exact output you're looking for:
sys.stdout.write("[%-20s] %d%%" % ('='*i, 5*i))
sys.stdout.flush()
sleep(0.25)

これは、Python 3.4.3 64ビットのW7-64で正常に機能すると言えますが、ネイティブコンソールでのみ機能します。ただし、spyder 3.0.0devの組み込みコンソールを使用する場合、改行がまだ存在します。これには少し時間がかかったので、ここでこの観察を報告したいと思います。


2

ここや他の場所でいくつかの答えに基づいて、進行状況バーと経過時間/推定残り時間を表示するこの簡単な関数を作成しました。ほとんどのUNIXベースのマシンで動作するはずです。

import time
import sys

percent = 50.0
start = time.time()
draw_progress_bar(percent, start)


def draw_progress_bar(percent, start, barLen=20):
sys.stdout.write("\r")
progress = ""
for i in range(barLen):
    if i < int(barLen * percent):
        progress += "="
    else:
        progress += " "

elapsedTime = time.time() - start;
estimatedRemaining = int(elapsedTime * (1.0/percent) - elapsedTime)

if (percent == 1.0):
    sys.stdout.write("[ %s ] %.1f%% Elapsed: %im %02is ETA: Done!\n" % 
        (progress, percent * 100, int(elapsedTime)/60, int(elapsedTime)%60))
    sys.stdout.flush()
    return
else:
    sys.stdout.write("[ %s ] %.1f%% Elapsed: %im %02is ETA: %im%02is " % 
        (progress, percent * 100, int(elapsedTime)/60, int(elapsedTime)%60,
         estimatedRemaining/60, estimatedRemaining%60))
    sys.stdout.flush()
    return

2

これは非常にシンプルなアプローチで、どのループでも使用できます。

#!/usr/bin/python
for i in range(100001):
    s =  ((i/5000)*'#')+str(i)+(' %')
    print ('\r'+s),

「#」は何をしますか?
unseen_rider 2017年

@unseen_riderここでの「#」は、ループの反復回数が増えるにつれて繰り返される単なる記号です。
NILESH KUMAR

2

まだ簡単です

import sys
total_records = 1000
for i in range (total_records):
    sys.stdout.write('\rUpdated record: ' + str(i) + ' of ' + str(total_records))
    sys.stdout.flush()

キーは整数型を文字列に変換することです。


2

Mark Rushakoffのソリューションで説明されているように、キャリッジリターン文字を出力してsys.stdout.write('\r')、カーソルを行の先頭にリセットできます。そのソリューションを一般化するには、Python 3のf-Stringsも実装しながら、次を使用できます。

from time import sleep
import sys

n_bar = 50
iterable = range(33)  # for demo purposes
n_iter = len(iterable)
for i, item in enumerate(iterable):
    j = (i + 1) / n_iter

    sys.stdout.write('\r')
    sys.stdout.write(f"[{'=' * int(n_bar * j):{n_bar}s}] {int(100 * j)}%")
    sys.stdout.flush()

    sleep(0.05)  
    # do something with <item> here

1

PyProgを試してください。PyProgは、Pythonのオープンソースライブラリで、超カスタマイズ可能な進行状況インジケーターとバーを作成します。

現在バージョン1.0.2です。Githubでホストされ、PyPIで利用できます(下のリンク)。Python 3および2と互換性があり、Qt Consoleでも使用できます。

とても使いやすいです。次のコード:

import pyprog
from time import sleep

# Create Object
prog = pyprog.ProgressBar(" ", " ", total=34, bar_length=26, complete_symbol="=", not_complete_symbol=" ", wrap_bar_prefix=" [", wrap_bar_suffix="] ", progress_explain="", progress_loc=pyprog.ProgressBar.PROGRESS_LOC_END)
# 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()

あなたが望むものを正確に生成します(バーの長さも!):

[===========               ] 45%
[===============           ] 60%
[==========================] 100%

進行状況バーをカスタマイズするその他のオプションについては、このWebサイトのGithubページにアクセスしてください。

シンプルだが非常にカスタマイズ可能なプログレスバーライブラリが必要だったので、実際にPyProgを作成しました。簡単にインストールできますpip install pyprog

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


1

@ Mark-Rushakoffの回答を使用して、sysライブラリを呼び出す必要がない、より簡単な方法を考え出しました。Python 3で動作します。Windowsでテスト済み:

from time import sleep
for i in range(21):
    # the exact output you're looking for:
    print ("\r[%-20s] %d%%" % ('='*i, 5*i), end='')
    sleep(0.25)

別の質問への回答で 説明されているのprintは、入力をフォーマットし、指定されたオブジェクトの書き込み関数を呼び出す薄いラッパーです。デフォルトでは、このオブジェクトはsys.stdoutです。
Steven C. Howell

0

@ Mark-Rushakoffのソリューションを使用して作成したものを以下に示します。端子幅に適応的に調整します。

from time import sleep
import os
import sys
from math import ceil

l = list(map(int,os.popen('stty size','r').read().split()))
col = l[1]
col = col - 6

for i in range(col):
    sys.stdout.write('\r')
    getStr = "[%s " % ('='*i)
    sys.stdout.write(getStr.ljust(col)+"]"+"%d%%" % (ceil((100/col)*i)))
    sys.stdout.flush()
    sleep(0.25)
print("")
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.