Python에서 콘솔 출력 교체


106

특정 C / C ++ 프로그램에서와 같이 Python에서 멋진 콘솔 카운터 중 하나를 어떻게 만들 수 있는지 궁금합니다.

나는 일을하는 루프가 있고 현재 출력은 다음과 같습니다.

Doing thing 0
Doing thing 1
Doing thing 2
...

더 깔끔한 것은 마지막 라인 업데이트 만하는 것입니다.

X things done.

여러 콘솔 프로그램에서 이것을 보았고 파이썬에서 이것을 어떻게 할 것인지 궁금합니다.


3
저주를 살펴 봐야 합니다.
Björn Pollex


1
@ BjörnPollex curses는 과잉입니다 (허용되는 답변 참조).
Alexey

답변:


151

쉬운 해결책은 "\r"줄 바꿈을 추가하지 않고 문자열 앞에 쓰는 것입니다 . 문자열이 짧아지지 않으면 충분합니다 ...

sys.stdout.write("\rDoing thing %i" % i)
sys.stdout.flush()

진행률 표시 줄이 약간 더 정교합니다. 이것은 제가 사용하는 것입니다.

def startProgress(title):
    global progress_x
    sys.stdout.write(title + ": [" + "-"*40 + "]" + chr(8)*41)
    sys.stdout.flush()
    progress_x = 0

def progress(x):
    global progress_x
    x = int(x * 40 // 100)
    sys.stdout.write("#" * (x - progress_x))
    sys.stdout.flush()
    progress_x = x

def endProgress():
    sys.stdout.write("#" * (40 - progress_x) + "]\n")
    sys.stdout.flush()

당신은 호출 startProgress작업의 설명을 통과 한 후 progress(x)위치를 x마지막으로 백분율입니다endProgress()


2
문자열이 이전 문자열보다 짧으면 어떻게됩니까?
math2001

6
@ math2001 공백으로 패딩.
felipsmartins

코드의 처음 2 줄에만 투표했습니다. 일부 경우 진행률 표시 줄 부분이 느려집니다. 어쨌든 감사합니다 @ 6502
WaterRocket8236

일부 프로그램 (restic , flatpak)은 여러 줄의 콘솔 출력을 업데이트 할 수 있습니다. 이것이 어떻게 이루어질 수 있는지 아십니까?
Alexey

1
@Alexey : ANSI 이스케이프 코드를 사용하여 커서를 이동하고 화면의 일부를 지우고 색상을 변경할 수 있습니다 ... en.wikipedia.org/wiki/ANSI_escape_code
6502

39

더 우아한 솔루션은 다음과 같습니다.

def progressBar(current, total, barLength = 20):
    percent = float(current) * 100 / total
    arrow   = '-' * int(percent/100 * barLength - 1) + '>'
    spaces  = ' ' * (barLength - len(arrow))

    print('Progress: [%s%s] %d %%' % (arrow, spaces, percent), end='\r')

이 함수를 value및로 호출하면 endvalue결과는

Progress: [------------->      ] 69 %

참고 : 여기에 Python 2.x 버전이 있습니다 .


더 나은 진행률 표시 줄과 스피너를 사용하려면 Halo 를 사용해야합니다 .
Aravind Voggu

17

파이썬 3 에서는 다음과 같이 동일한 행에 인쇄 할 수 있습니다.

print('', end='\r')

최신 업데이트 및 진행 상황을 추적하는 데 특히 유용합니다.

루프의 진행 상황을보고 싶다면 여기에서 tqdm 추천 합니다. 현재 반복 및 총 반복을 예상 완료 시간과 함께 진행률 표시 줄로 인쇄합니다. 매우 유용하고 빠릅니다. python2 및 python3에서 작동합니다.


7

다른 대답이 더 좋을 수도 있지만 여기에 제가하고있는 일이 있습니다. 먼저 백 스페이스 문자를 인쇄하는 progress라는 함수를 만들었습니다.

def progress(x):
    out = '%s things done' % x  # The output
    bs = '\b' * 1000            # The backspace
    print bs,
    print out,

그런 다음 내 주요 기능의 루프에서 다음과 같이 호출했습니다.

def main():
    for x in range(20):
        progress(x)
    return

이것은 물론 전체 라인을 지울 수 있지만 원하는 것을 정확하게 수행하기 위해 그것을 망칠 수 있습니다. 이 방법을 사용하여 진행률 표시 줄을 만들었습니다.


4
작동하지만 이전 줄에 다음 줄보다 더 많은 문자가있는 경우 새 줄 끝 이후의 문자는 이전 줄에서 그대로 유지됩니다. "
Lil 'Bits

7

몇 년 후 (내가 한 것처럼) 우연히 발견 한 사람을 위해 진행률 표시 줄이 감소하고 증가 할 수 있도록 6502의 방법을 약간 조정했습니다. 약간 더 많은 경우에 유용합니다. 훌륭한 도구에 대해 6502에게 감사드립니다!

기본적으로 유일한 차이점은 progress (x)가 호출 될 때마다 #s와 -s의 전체 행이 기록되고 커서는 항상 막대의 시작 부분으로 반환된다는 것입니다.

def startprogress(title):
    """Creates a progress bar 40 chars long on the console
    and moves cursor back to beginning with BS character"""
    global progress_x
    sys.stdout.write(title + ": [" + "-" * 40 + "]" + chr(8) * 41)
    sys.stdout.flush()
    progress_x = 0


def progress(x):
    """Sets progress bar to a certain percentage x.
    Progress is given as whole percentage, i.e. 50% done
    is given by x = 50"""
    global progress_x
    x = int(x * 40 // 100)                      
    sys.stdout.write("#" * x + "-" * (40 - x) + "]" + chr(8) * 41)
    sys.stdout.flush()
    progress_x = x


def endprogress():
    """End of progress bar;
    Write full bar, then move to next line"""
    sys.stdout.write("#" * 40 + "]\n")
    sys.stdout.flush()

1
그래도 코드에 의해 너무 자주 호출되면 속도가 느려질 수 있다는 것을
알았으므로

6

내가 잘 이해했다면 (확실하지 않음) 인쇄 <CR>하고 싶지 <LR>않습니까?

가능하다면 콘솔 터미널이이를 허용하는 한 (출력 si가 파일로 리디렉션 될 때 중단됩니다).

from __future__ import print_function
print("count x\r", file=sys.stdout, end=" ")

5

print()함수를 보면 sys 라이브러리를 사용하지 않고 할 수 있습니다.

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

내 코드는 다음과 같습니다.

def update(n):
    for i in range(n):
        print("i:",i,sep='',end="\r",flush=True)
        #time.sleep(1)

5

나는 이것을 얼마 전에 썼고 정말 행복합니다. 자유롭게 사용하십시오.

그것은 소요 indextotal선택적으로 title또는 bar_length. 완료되면 모래 시계를 확인 표시로 바꿉니다.

⏳ Calculating: [████░░░░░░░░░░░░░░░░░░░░░] 18.0% done

✅ Calculating: [█████████████████████████] 100.0% done

이를 테스트하기 위해 실행할 수있는 예제를 포함했습니다.

import sys
import time

def print_percent_done(index, total, bar_len=50, title='Please wait'):
    '''
    index is expected to be 0 based index. 
    0 <= index < total
    '''
    percent_done = (index+1)/total*100
    percent_done = round(percent_done, 1)

    done = round(percent_done/(100/bar_len))
    togo = bar_len-done

    done_str = '█'*int(done)
    togo_str = '░'*int(togo)

    print(f'\t⏳{title}: [{done_str}{togo_str}] {percent_done}% done', end='\r')

    if round(percent_done) == 100:
        print('\t✅')


r = 50
for i in range(r):
    print_percent_done(i,r)
    time.sleep(.02)

또한 shutil.get_terminal_size()관심있는 경우 사용하는 터미널 너비에 따라 반응 형 진행률 표시 줄이있는 버전이 있습니다 .


4

Aravind Voggu 의 예에 약간 더 많은 기능을 추가했습니다 .

def progressBar(name, value, endvalue, bar_length = 50, width = 20):
        percent = float(value) / endvalue
        arrow = '-' * int(round(percent*bar_length) - 1) + '>'
        spaces = ' ' * (bar_length - len(arrow))
        sys.stdout.write("\r{0: <{1}} : [{2}]{3}%".format(\
                         name, width, arrow + spaces, int(round(percent*100))))
        sys.stdout.flush()
        if value == endvalue:     
             sys.stdout.write('\n\n')

이제 이전 진행률 표시 줄을 교체하지 않고도 여러 진행률 표시 줄을 생성 할 수 있습니다.

name너비가 고정 된 값으로 도 추가 했습니다.

두 개의 루프와 두 번의 progressBar()경우 결과 사용은 다음과 같습니다.

진행률 표시 줄 애니메이션


-1

아래 코드는 이전 숫자를 대체하여 0.3 초마다 0에서 137까지 메시지를 계산합니다.

백 스테이지 할 기호 수 = 자릿수.

stream = sys.stdout
for i in range(137):
    stream.write('\b' * (len(str(i)) + 10))
    stream.write("Message : " + str(i))
    stream.flush()
    time.sleep(0.3)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.