상태 표시 줄 및 백분율을 인쇄하는 Python


160

아래와 같이 상태 표시 줄을 구현하려면

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

이것을 stdout으로 인쇄하고 다른 줄로 인쇄하지 않고 새로 고치기를 원합니다. 이것을하는 방법?


매우 멋진 애니메이션 외에 인쇄, 처리량 및 에타를보고 일시 중지 할 수있는 새로운 종류의 진행률 표시 줄을 게시했습니다! 봐 주시기 바랍니다 : github.com/rsalmei/alive-progress를 ! 살아있는 진행
rsalmei

답변:


146

당신이에서 얻을 수있는 파이썬 모듈있다 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 progressbar하거나 pip install progressbarpip를 선호하는 경우 사용할 수 있습니다 .


모든 답변은 훌륭하지만 모듈이 가장 좋습니다. 모두에게 감사 드려요.
Stan

8
아마도이 예제는 bar.start()?
Jim Raynor

2
내 컴퓨터에서 작동하지 않습니다bar.start()
Zach

1
이 모듈은 2 년 이상 업데이트되지 않았습니다. 새 소프트웨어에는 사용하지 마십시오!
Navin

4
설치 : sudo -H pip install progressbar2.
Martin Thoma

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에서도 작동하기 때문에 표시된 답변보다 낫습니다.
Gerhard Hagerer 2016 년

내가 쓰는 문자열을 null로 종료하더라도 줄 끝에 이상한 문자가 나타나는 이유는 무엇입니까?
reservoirman

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)) 반복 가능한 객체를 열거하는 것입니다. 이 수정 사항을 추천했지만 거부되었습니다. 분명히 기능은 "게시물의 원래 의도와 다릅니다".
Steven C. Howell

1
임의의 크기의 n,, sys.stdout.write("[{:{}}] {:.1f}%".format("="*i, n-1, (100/(n-1)*i)))Python 3에만 적용
GabrielChu

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 iterable을 감쌀 수 있습니다.



1
와우,이 tqdm은 놀랍고 사용하기 쉽습니다 :).
Sidahmed

6
이것은 가장 간단한 해결책입니다
kd88

2
그것은 Anaconda distrib와 함께 제공됩니다! (파이썬 3.5 이상 이상)
Jacquot

고마워, 놀랍고 간단하며 효과적
DavideL

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

나를 위해 첫 번째 줄은 커서로 수정되지 않으며 두 번째 줄만 수정됩니다. 따라서 진행 표시 줄에 대해 여러 줄을 얻었으며 다음과 같이 한 줄을 얻었습니다.] 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

나는 소수 자릿수가 필요하지 않다고 생각한다. 즉 round (progress * 100,2)
Andrés Sánchez

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  

완전한! 모듈 필요 없음
유리한

3

오늘이 스레드에 왔으며 Mark Rushakoff 에서이 솔루션을 시도한 후

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)

나는 이것이 파이썬 3.4.3 64 비트가있는 W7-64에서 잘 작동하지만 기본 콘솔에서만 작동한다고 말할 수 있습니다. 그러나 내장 된 스파이더 3.0.0dev 콘솔을 사용할 때 줄 바꿈이 여전히 존재합니다. 이 과정을 이해하는 데 시간이 걸렸으므로이 관찰 내용을 여기에보고하고 싶습니다.


2

여기 및 다른 곳에서 일부 답변을 기반으로 진행률 표시 줄과 경과 / 예상 잔여 시간을 표시하는이 간단한 기능을 작성했습니다. 대부분의 유닉스 기반 머신에서 작동합니다.

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

@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')하여 커서를 줄의 시작 부분으로 재설정 할 수 있습니다 . 또한 구현하면서, 그 해결책을 일반화하기 위해 파이썬 3의 F-문자열을 , 당신은 사용할 수 있습니다

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%

진행률 표시 줄을 사용자 정의하기위한 추가 옵션을 보려면이 웹 사이트의 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.