파이썬에서 이전 인쇄를 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.