파이썬에서 이전 인쇄를 stdout에 덮어 쓰는 방법은 무엇입니까?


113

다음 코드가있는 경우 :

for x in range(10):
     print x

나는 출력을 얻을 것이다

1
2
etc..

내가하고 싶은 것은 줄 바꿈을 인쇄하는 대신 이전 값을 바꾸고 같은 줄의 새 값으로 덮어 쓰는 것입니다.



참고로, 이전 줄 이 현재 줄보다 길면 전체 줄을 플러시 할 수있는 답을 얻으십시오 .
과일

답변:


119

한 가지 방법은 캐리지 리턴 ( '\r') 문자를 사용하여 다음 행으로 이동하지 않고 행의 시작으로 돌아가는 것입니다.

for x in range(10):
    print '{0}\r'.format(x),
print

print 문 끝에있는 쉼표는 다음 행으로 이동하지 않도록 지시합니다. 마지막 print 문은 다음 줄로 이동하므로 프롬프트가 최종 출력을 덮어 쓰지 않습니다.

최신 정보

이제 Python 2가 EOL이므로 Python 3 답변이 더 합리적입니다. Python 3.5 이하의 경우 :

for x in range(10):
    print('{}\r'.format(x), end="")
print()

Python 3.6 이상에서는 f- 문자열이 더 잘 읽 힙니다.

for x in range(10):
    print(f'{x}\r', end="")
print()

작동하지만 몇 가지 부분을 이해하지 못합니다 ... '{0}'및 .format
ccwhite1

7
이것은 Python 2.6에서 도입되었으며 (내가 말했듯이) Python 3에서 문자열 형식을 지정하는 표준 방법입니다. %조작이 중단된다. 기본적으로 모든 문자열에는 이제 형식화 방법이 있습니다. 이 경우 {0}"에 대한 첫 번째 인수"를 의미합니다 format()(계수는 0에서 시작).
Mike DeSimone 2011 년

일부 Windows 전용 소프트웨어를 사용해야하고 VM을 실행할 수없는 경우 옵션이 아닙니다.
마이크 DeSimone

2
그리고 만약 당신이 교차 터미널이되고 싶다면 re.sub(r'\$<\d+>[/*]?', '', curses.tigetstr('el') or ''), 사용자가 가지고있는 터미널에 대해 정확한 라인 끝까지 지우기 문자열을 제공 할 것입니다. curses와 같은 것으로 초기화 하고 출력이 파일로 리디렉션되지 않는지 확인 curses.setupterm(fd=sys.stdout.fileno())하는 sys.stdout.isatty()데 사용하십시오. 커서 제어 및 색상을 지원하는 전체 Python 모듈 은 code.activestate.com/recipes/475116 을 참조하십시오 .
Mike DeSimone

1
@PhilMacKay : 내 Mac에서 파이썬으로 시도했습니다 : In [3] : print "Thing to erase \ r",; time.sleep (1); print "-------------- \ r", -------------- 문제가 Windows이고 다른 줄 끝이라고 생각합니다. 시도해보십시오 : import curses; curses.setupterm(fd=sys.stdout.fileno()); print(hex(curses.tigetstr('cr')));줄의 시작으로 이동하려면 문자 시퀀스의 16 진 코드를 인쇄해야합니다.
Mike DeSimone

107

Google을 통해 여기에 왔지만 Python 3을 사용하고 있으므로 Python 3에서 작동하는 방법은 다음과 같습니다.

for x in range(10):
    print("Progress {:2.1%}".format(x / 10), end="\r")

여기 관련 답변 : print 문 뒤에 줄 바꿈을 어떻게 억제 할 수 있습니까?


3
나는 이것을 시도했고 대부분 잘 작동합니다. 첫 번째 루프 인쇄 경우 : 유일한 문제는 예를 들어 그 라인 이전에 출력을 삭제하지 것입니다 testing및 두 번째 루프는 인쇄 test계속 될 것입니다 두 번째 패스를 출력 testing- 지금은 Nagasaki45 @이 지적 볼
에릭 Uldall

15
ipython 노트북에서해야 할 일 :print("\r", message, end="")
grisaitis

1
이것은 훌륭하게 작동하지만 줄을 지우지는 않지만 다음 인쇄에서 충분한 공백을 사용하면 작업이 수행됩니다 (우아하지는 않지만). 내가 추가 할 수있는 한 가지 의견은 VS Code의 디버그 콘솔에서는 작동하지 않지만 터미널에서는 작동한다는 것입니다.
PhilMacKay

31

@Mike DeSimone 답변은 아마도 대부분의 경우 작동합니다. 그러나...

for x in ['abc', 1]:
    print '{}\r'.format(x),

-> 1bc

이것은 '\r'유일한 줄의 시작 부분으로 돌아가지만 출력을 지우지 않기 때문입니다.

편집 : 더 나은 솔루션 (아래의 이전 제안보다)

POSIX 지원이 충분하다면 다음은 현재 줄을 지우고 커서를 시작 부분에 둡니다.

print '\x1b[2K\r',

ANSI 이스케이프 코드를 사용하여 터미널 라인을 지 웁니다. 더 많은 정보는 위키피디아 와이 훌륭한 강연 에서 찾을 수 있습니다 .

이전 답변

내가 찾은 (그다지 좋지 않은) 해결책은 다음과 같습니다.

last_x = ''
for x in ['abc', 1]:
    print ' ' * len(str(last_x)) + '\r',
    print '{}\r'.format(x),
    last_x = x

-> 1

한 가지 장점은 창문에서도 작동한다는 것입니다.


1
나는 (Windows에서도) 제대로 작동하는 '이전 답변'에서 기능을 만들었습니다. 내 답변을 참조하십시오. stackoverflow.com/a/43952192/965332
erb

25

이 스레드를 방문하기 전에 동일한 질문이있었습니다. 나를 위해 sys.stdout.write는 버퍼를 올바르게 플러시하는 경우에만 작동했습니다.

for x in range(10):
    sys.stdout.write('\r'+str(x))
    sys.stdout.flush()

플러시하지 않고 결과는 스크립트 끝 부분에만 인쇄됩니다.


stringvar.ljust(10,' ')길이가 가변적 인 문자열의 경우 처럼 나머지 문자열을 공백으로 채우는 것도 좋습니다 .
Annarfych

@chris, Don et al. 이것은 Python 2이고 대부분의 다른 답변은 Python 3입니다. 모두가 이제 Python 3을 사용해야합니다. Python 2는 2020
단종

18

개행을 억제하고 인쇄하십시오 \r.

print 1,
print '\r2'

또는 stdout에 쓰십시오.

sys.stdout.write('1')
sys.stdout.write('\r2')

9

이 시도:

import time
while True:
    print("Hi ", end="\r")
    time.sleep(1)
    print("Bob", end="\r")
    time.sleep(1)

그것은 나를 위해 일했습니다. end="\r"부분은 이전 줄을 덮어하고있다.

경고!

를 인쇄 hi한 다음를 hello사용하여 인쇄 하면 출력이 이전 두 글자를 덮어 썼기 때문에 \r얻을 수 hillo있습니다. hi공백으로 인쇄하면 (여기에 표시되지 않음) hi. 이 문제를 해결하려면을 사용하여 공백을 인쇄하십시오 \r.


1
이것은 나를 위해 작동하지 않습니다. 나는 그 코드를 처리했지만 내 출력은 Hi BobHi BobHi BobHi BobHi Bob. Python 3.7.1
PaulMag

1
그러나 Rubixred의 대답은 효과가있었습니다. 기묘한. 저에게도 같은 방법으로 보입니다. 내가 보는 유일한 차이점 \r은 끝이 아니라 시작에 있다는 것입니다.
PaulMag 2014

7

이 페이지의 어떤 솔루션도 IPython 에서 작동하도록 할 수 없었지만 @ Mike-Desimone의 솔루션에 대한 약간의 변형이 작업을 수행했습니다. 캐리지 리턴으로 줄을 종료하는 대신 캐리지 리턴으로 줄을 시작 합니다.

for x in range(10):
    print '\r{0}'.format(x),

또한이 방법에는 두 번째 print 문이 필요하지 않습니다.


심지어 PyDev 콘솔에서는 작동하지 않으며 print ()의 닫는 괄호 뒤에 쉼표도 없습니다.
Noumenon

저에게 효과가 없었습니다. 프로세스가 완료되면 최종 결과 (예 : "다운로드 진행률 100 %") 만 기록합니다.
Alexandre

2
@Alexandre IPython 또는 후속 Jupyter에서 잘 작동합니다. 버퍼를 비워야합니다. stackoverflow.com/questions/17343688/…
March Ho

7
for x in range(10):
    time.sleep(0.5) # shows how its working
    print("\r {}".format(x), end="")

time.sleep (0.5)는 이전 출력이 어떻게 지워지고 새 출력이 "\ r"로 인쇄되는지 보여줍니다. 인쇄 시작 메시지 일 때 새 출력 전에 이전 출력을 지 웁니다.


7

이것은 Windows 및 Python 3.6에서 작동합니다.

import time
for x in range(10):
    time.sleep(0.5)
    print(str(x)+'\r',end='')

5

받아 들여진 대답은 완벽 하지 않습니다 . 처음 인쇄 된 줄은 그대로 유지되고 두 번째 인쇄가 전체 새 줄을 덮지 않으면 쓰레기 텍스트로 끝납니다.

문제를 설명하기 위해이 코드를 스크립트로 저장하고 실행 (또는 살펴보기) :

import time

n = 100
for i in range(100):
    for j in range(100):
        print("Progress {:2.1%}".format(j / 100), end="\r")
        time.sleep(0.01)
    print("Progress {:2.1%}".format(i / 100))

출력은 다음과 같습니다.

Progress 0.0%%
Progress 1.0%%
Progress 2.0%%
Progress 3.0%%

나를 위해 일하는 것은 영구 인쇄를 남기기 전에 줄을 지우는 것입니다. 특정 문제에 자유롭게 조정하십시오.

import time

ERASE_LINE = '\x1b[2K' # erase line command
n = 100
for i in range(100):
    for j in range(100):
        print("Progress {:2.1%}".format(j / 100), end="\r")
        time.sleep(0.01)
    print(ERASE_LINE + "Progress {:2.1%}".format(i / 100)) # clear the line first

이제 예상대로 인쇄됩니다.

Progress 0.0%
Progress 1.0%
Progress 2.0%
Progress 3.0%

5

@ Nagasaki45의 대답에 대한 더 깔끔하고 "플러그 앤 플레이"버전이 있습니다. 여기의 다른 많은 답변과 달리 길이가 다른 문자열에서도 제대로 작동합니다. 인쇄 된 마지막 줄의 길이만큼 공백이있는 줄을 지워이를 달성합니다. Windows에서도 작동합니다.

def print_statusline(msg: str):
    last_msg_length = len(print_statusline.last_msg) if hasattr(print_statusline, 'last_msg') else 0
    print(' ' * last_msg_length, end='\r')
    print(msg, end='\r')
    sys.stdout.flush()  # Some say they needed this, I didn't.
    print_statusline.last_msg = msg

용법

다음과 같이 사용하십시오.

for msg in ["Initializing...", "Initialization successful!"]:
    print_statusline(msg)
    time.sleep(1)

이 작은 테스트는 길이가 다른 경우에도 선이 제대로 지워지는 것을 보여줍니다.

for i in range(9, 0, -1):
    print_statusline("{}".format(i) * i)
    time.sleep(0.5)

5
이 우아하게 그냥 흰색 공간의 임의의 수 인쇄하지 않고 자사의 전체 길이에 이전의 출력을 청소 이것은 좋은 솔루션입니다 감사합니다 (I 이전에 의지 한 것입니다!)
토비 치사

2

아무도 백 스페이스 문자를 사용하지 않는다는 것에 조금 놀랐습니다. 여기에 그것을 사용하는 것이 있습니다.

import sys
import time

secs = 1000

while True:
    time.sleep(1)  #wait for a full second to pass before assigning a second
    secs += 1  #acknowledge a second has passed

    sys.stdout.write(str(secs))

    for i in range(len(str(secs))):
        sys.stdout.write('\b')

이 방법을 사용한 후에는 플러시해야합니다. 그렇지 않으면 화면에 아무것도 인쇄되지 않을 수 있습니다. sys.stdout.flush()
Gabriel Fair

2

(Python3) 이것이 저에게 효과적이었습니다. \ 010 만 사용하면 문자가 남기 때문에 거기에 있던 것을 덮어 쓰도록 약간 조정했습니다. 이렇게하면 첫 번째 항목 인쇄 전에 무언가를 가질 수 있으며 항목의 길이 만 제거 할 수 있습니다.

print("Here are some strings: ", end="")
items = ["abcd", "abcdef", "defqrs", "lmnop", "xyz"]
for item in items:
    print(item, end="")
    for i in range(len(item)): # only moving back the length of the item
        print("\010 \010", end="") # the trick!
        time.sleep(0.2) # so you can see what it's doing

2

이전 답변을 기반으로 한 답변이 더 있습니다.

pbar.py의 내용 : import sys, shutil, datetime

last_line_is_progress_bar=False


def print2(print_string):
    global last_line_is_progress_bar
    if last_line_is_progress_bar:
        _delete_last_line()
        last_line_is_progress_bar=False
    print(print_string)


def _delete_last_line():
    sys.stdout.write('\b\b\r')
    sys.stdout.write(' '*shutil.get_terminal_size((80, 20)).columns)
    sys.stdout.write('\b\r')
    sys.stdout.flush()


def update_progress_bar(current, total):
    global last_line_is_progress_bar
    last_line_is_progress_bar=True

    completed_percentage = round(current / (total / 100))
    current_time=datetime.datetime.now().strftime('%m/%d/%Y-%H:%M:%S')
    overhead_length = len(current_time+str(current))+13
    console_width = shutil.get_terminal_size((80, 20)).columns - overhead_length
    completed_width = round(console_width * completed_percentage / 100)
    not_completed_width = console_width - completed_width
    sys.stdout.write('\b\b\r')

    sys.stdout.write('{}> [{}{}] {} - {}% '.format(current_time, '#'*completed_width, '-'*not_completed_width, current,
                                        completed_percentage),)
    sys.stdout.flush()

스크립트 사용법 :

import time
from pbar import update_progress_bar, print2


update_progress_bar(45,200)
time.sleep(1)

update_progress_bar(70,200)
time.sleep(1)

update_progress_bar(100,200)
time.sleep(1)


update_progress_bar(130,200)
time.sleep(1)

print2('some text that will re-place current progress bar')
time.sleep(1)

update_progress_bar(111,200)
time.sleep(1)

print('\n') # without \n next line will be attached to the end of the progress bar
print('built in print function that will push progress bar one line up')
time.sleep(1)

update_progress_bar(111,200)
time.sleep(1)

1

여기 내 해결책이 있습니다! Windows 10, Python 3.7.1

이 코드가 왜 작동하는지 잘 모르겠지만 원래 줄을 완전히 지 웁니다. 이전 답변에서 편집했습니다. 다른 답변은 처음으로 선을 반환하지만 이후 짧은 라인이 있다면, 그것은처럼 엉망으로 보일 것 hello으로 변합니다 byelo.

import sys
#include ctypes if you're on Windows
import ctypes
kernel32 = ctypes.windll.kernel32
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
#end ctypes

def clearline(msg):
    CURSOR_UP_ONE = '\033[K'
    ERASE_LINE = '\x1b[2K'
    sys.stdout.write(CURSOR_UP_ONE)
    sys.stdout.write(ERASE_LINE+'\r')
    print(msg, end='\r')

#example
ig_usernames = ['beyonce','selenagomez']
for name in ig_usernames:
    clearline("SCRAPING COMPLETE: "+ name)

출력-이전 텍스트가 표시되지 않고 각 줄이 다시 작성됩니다.

SCRAPING COMPLETE: selenagomez

다음 줄 (같은 줄에 완전히 다시 작성) :

SCRAPING COMPLETE: beyonce

0

전체 줄을 덮어 쓰는 것이 더 좋습니다. 그렇지 않으면 새 줄이 더 짧으면 새 줄이 이전 줄과 혼합됩니다.

import time, os
for s in ['overwrite!', 'the!', 'whole!', 'line!']:
    print(s.ljust(os.get_terminal_size().columns - 1), end="\r")
    time.sleep(1)

columns - 1Windows 에서 사용해야 했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.