programing

이전 인쇄물을 stdout으로 덮어쓰는 방법은 무엇입니까?

javamemo 2023. 6. 14. 21:37
반응형

이전 인쇄물을 stdout으로 덮어쓰는 방법은 무엇입니까?

만약 내가 다음 코드를 가지고 있다면:

for x in range(10):
     print(x)

의 결과물을 얻을 것입니다.

1
2
etc..

제가 하고 싶은 것은 새 줄을 인쇄하는 것이 아니라 이전 값을 대체하여 같은 줄의 새 값으로 덮어쓰는 것입니다.

단순 버전

리턴을 입니다.'\r'줄로 입니다.). 다음 줄로 이동하지 않고 줄의 시작으로 돌아가는 문자입니다.

파이썬 3

for x in range(10):
    print(x, end='\r')
print()

Python 2.7과의 상위 호환

from __future__ import print_function
for x in range(10):
    print(x, end='\r')
print()

파이썬 2.7

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

Python 2.0-2.6

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

후자의 두 개의 경우(Python 2-only) 인쇄 문 끝에 있는 쉼표는 다음 행으로 가지 말라고 말합니다.마지막 인쇄 문이 다음 행으로 이동하므로 프롬프트가 최종 출력을 덮어쓰지 않습니다.

라인 청소

수 " of line" 시퀀스인 " to end"를만 하면 .'\x1b[1K'('\x1b'ESC):

for x in range(75):
    print('*' * (75 - x), x, end='\x1b[1K\r')
print()

구글을 통해 여기까지 왔지만 Python 3을 사용하고 있기 때문에, Python 3에서 이것이 어떻게 작동하는지는 다음과 같습니다.

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

관련 답변:문을 인쇄한 후 새 줄을 표시하지 않으려면 어떻게 해야 합니까?

@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

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

이 스레드를 방문하기 전에 같은 질문이 있었습니다.저는 sys.stdout입니다.버퍼를 적절하게 플러시해야 write worked.

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

플러시하지 않고 스크립트의 마지막 부분에만 결과가 인쇄됩니다.

바꿈을 새쇄줄 표 함 및 인\r.

print 1,
print '\r2'

또는 stdout에 씁니다.

sys.stdout.write('1')
sys.stdout.write('\r2')
for x in range(10):
    time.sleep(0.5) # shows how its working
    print("\r {}".format(x), end="")

time.sleep(0.5)은 메시지 인쇄 시작 시 이전 출력이 지워지고 새 출력이 "\r" 인쇄되는 방법을 보여줍니다. 새 출력 전에 이전 출력이 지워집니다.

사용해 보십시오.

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.

여기 @나가사키45의 대답을 더 깨끗하고 더 "플러그 앤 플레이" 버전이 있습니다.여기에 나와 있는 다른 많은 답변과 달리 길이가 다른 문자열에서 올바르게 작동합니다.마지막 줄 인쇄 길이만큼 공백이 있는 줄을 지우면 됩니다.Windows에서도 작동합니다.

def print_statusline(msg: str):
    last_msg_length = len(getattr(print_statusline, 'last_msg', ''))
    print(' ' * last_msg_length, end='\r')
    print(msg, end='\r')
    sys.stdout.flush()  # Some say they needed this, I didn't.
    setattr(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)

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

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

이 페이지의 솔루션을 IPython에서 사용할 수는 없었지만, @Mike-Desimone의 솔루션을 약간 변형시켜 사용했습니다. 캐리지 리턴으로 라인을 종료하는 대신 캐리지 리턴으로 라인을 시작하십시오.

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

또한 이 방법은 두 번째 인쇄문을 필요로 하지 않습니다.

승인된 답변이 완벽하지 않습니다.처음에 인쇄된 줄은 그대로 유지되며 두 번째 인쇄가 새 줄 전체를 덮지 않으면 가비지 텍스트가 표시됩니다.

문제를 설명하려면 이 코드를 스크립트로 저장하고 실행합니다(또는 보기만 하면 됩니다).

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%

저는 아무도 백스페이스 캐릭터를 사용하지 않는다는 것이 조금 놀랍습니다.여기 그것을 사용하는 것이 있습니다.

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

내 해결책이 여기 있습니다!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

(파이썬3)이것이 저에게 효과가 있었습니다.그냥 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

앞의 답변을 토대로 답변을 하나 더 드립니다.

pbar의 내용입니다.py: 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)

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

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(윈도우).

이것은 Windows에서 Spyder의 Python 3.7.9를 사용하여 작동했습니다.

from IPython.display import clear_output
from time import sleep

def print_and_overwrite(text):
    '''Remember to add print() after the last print that you want to overwrite.'''
    clear_output(wait=True)
    print(text, end='\r')

for i in range(15):
    #I print the results backwards (from 15 to 1), to test shorter strings
    message = "Iteration %d out of 15" %(15-i)
    print_and_overwrite(message)
    sleep(0.5)

print() #This stops the overwriting
print("This will be on a new line")

어쨌든 누군가가 이전에 stdout에서 인쇄된 많은 줄을 다시 인쇄(지우기)하고 싶다면, 이 대답이 그에게 도움이 될 것입니다. (Thijmen Dam에게 이전에 인쇄된 줄 덮어쓰기).

ANSI 콘솔에서 특수 시퀀스를 사용할 수 있습니다.

\033[1A그리고.\033[K

먼저 커서를 올리고, 두 번째로 선을 완전히 지웁니다.

콘솔 지우기 예제(Python 3):

LINE_UP = '\033[1A'
LINE_CLEAR = '\033[K'
CONSOLE_HEIGHT = 24 #lines

def clear_console():
    for a in range(CONSOLE_HEIGHT):
        print(LINE_UP, end=LINE_CLEAR, flush=True)

또는 결국 단순하게(화면을 지우고 커서를 0.0으로 이동):

print('\033[2J', end='', flush=True)

커서만 배치하려면 다음을 사용합니다.

print('\033[<L>;<C>f', end='', flush=True)

<L>그리고.<C>이에 상응하는 선과 열입니다.

ANSI 이스케이프 시퀀스에 대한 소수 참조

이 스레드에서 본 반응을 바탕으로 모든 플랫폼에서 좋을 수 있는 멋진 작은 클래스를 만들었습니다.

import sys

class PrintSameLine:
"""Class to correctly print on same line"""

def __init__(self):
    self.last_message = ""

def print_msg(self, msg: str):
    print(" " * len(self.last_message), end="\r", flush=True)
    print(msg, end="\r", flush=True)
    self.last_message = msg


# Note printing in reverse so you can see how it works
prnt = PrintSameLine()
for i in reverse(range(10)):
    prnt.print_msg(str(i))

언급URL : https://stackoverflow.com/questions/5419389/how-to-overwrite-the-previous-print-to-stdout

반응형