Se eu tivesse o seguinte código:
for x in range(10):
print x
Eu obteria a saída de
1
2
etc..
O que eu gostaria de fazer é, em vez de imprimir uma nova linha, quero substituir o valor anterior e substituí-lo pelo novo valor na mesma linha.
Se eu tivesse o seguinte código:
for x in range(10):
print x
Eu obteria a saída de
1
2
etc..
O que eu gostaria de fazer é, em vez de imprimir uma nova linha, quero substituir o valor anterior e substituí-lo pelo novo valor na mesma linha.
Respostas:
Uma maneira é usar o '\r'caractere de retorno de carro ( ) para retornar ao início da linha sem avançar para a próxima linha:
for x in range(10):
print '{0}\r'.format(x),
print
A vírgula no final da instrução de impressão diz para não ir para a próxima linha. A última instrução de impressão avança para a próxima linha para que seu prompt não substitua sua saída final.
Agora que Python 2 é EOL, uma resposta de Python 3 faz mais sentido. Para Python 3.5 e anterior:
for x in range(10):
print('{}\r'.format(x), end="")
print()
No Python 3.6 e posterior, as strings f são lidas melhor:
for x in range(10):
print(f'{x}\r', end="")
print()
%operador está obsoleto. Basicamente, todas as strings agora têm um método de formatação . Nesse caso, {0}significa "o primeiro argumento para format()" (a contagem começa em 0).
re.sub(r'\$<\d+>[/*]?', '', curses.tigetstr('el') or '')fornecerá a seqüência correta de apagar até o fim da linha para qualquer terminal que o usuário tenha. Lembre-se de inicializar cursescom algo como curses.setupterm(fd=sys.stdout.fileno())e use sys.stdout.isatty()para ter certeza de que sua saída não está sendo redirecionada para um arquivo. Consulte code.activestate.com/recipes/475116 para um módulo Python completo com controle de cursor e suporte a cores.
import curses; curses.setupterm(fd=sys.stdout.fileno()); print(hex(curses.tigetstr('cr')));deve imprimir os códigos hexadecimais da seqüência de caracteres para ir para o início da linha.
Como acabei aqui por meio do Google, mas estou usando Python 3, é assim que funcionaria em Python 3:
for x in range(10):
print("Progress {:2.1%}".format(x / 10), end="\r")
Resposta relacionada aqui: Como posso suprimir a nova linha após uma declaração de impressão?
testinge sua segunda impressão de loop, testa saída após a segunda passagem ainda será testing- agora vejo que @ Nagasaki45 apontou isso
print("\r", message, end="")
A resposta de @Mike DeSimone provavelmente funcionará na maioria das vezes. Mas...
for x in ['abc', 1]:
print '{}\r'.format(x),
-> 1bc
Isso ocorre porque o '\r'único volta para o início da linha, mas não limpa a saída.
Se o suporte POSIX for suficiente para você, o seguinte limparia a linha atual e deixaria o cursor em seu início:
print '\x1b[2K\r',
Ele usa o código de escape ANSI para limpar a linha do terminal. Mais informações podem ser encontradas na wikipedia e nesta ótima palestra .
A solução (não tão boa) que encontrei se parece com esta:
last_x = ''
for x in ['abc', 1]:
print ' ' * len(str(last_x)) + '\r',
print '{}\r'.format(x),
last_x = x
-> 1
Uma vantagem é que também funciona no Windows.
Eu tinha a mesma pergunta antes de visitar este tópico. Para mim, o sys.stdout.write funcionou apenas se eu limpar o buffer corretamente, ou seja,
for x in range(10):
sys.stdout.write('\r'+str(x))
sys.stdout.flush()
Sem flushing, o resultado é impresso apenas no final do script
stringvar.ljust(10,' ')no caso de strings com comprimento variável.
Suprima a nova linha e imprima \r.
print 1,
print '\r2'
ou escreva para stdout:
sys.stdout.write('1')
sys.stdout.write('\r2')
Experimente isto:
import time
while True:
print("Hi ", end="\r")
time.sleep(1)
print("Bob", end="\r")
time.sleep(1)
Funcionou para mim A end="\r"parte está fazendo com que sobrescreva a linha anterior.
AVISO!
Se você imprimir e hi, em seguida, imprimir hellousando \r, você obterá hilloporque a saída escreveu sobre as duas letras anteriores. Se você imprimir hicom espaços (que não aparecem aqui), ele será impresso hi. Para corrigir isso, imprima os espaços usando \r.
Hi BobHi BobHi BobHi BobHi Bob. Python 3.7.1
\restá no início, e não no fim.
Não consegui fazer com que nenhuma das soluções desta página funcionasse para IPython , mas uma ligeira variação na solução de @Mike-Desimone resolveu: em vez de terminar a linha com o retorno de carro, comece a linha com o retorno de carro:
for x in range(10):
print '\r{0}'.format(x),
Além disso, essa abordagem não requer a segunda instrução de impressão.
for x in range(10):
time.sleep(0.5) # shows how its working
print("\r {}".format(x), end="")
time.sleep (0,5) é para mostrar como a saída anterior é apagada e a nova saída é impressa "\ r" quando está no início da mensagem de impressão, ela irá apagar a saída anterior antes da nova saída.
Isso funciona no Windows e python 3.6
import time
for x in range(10):
time.sleep(0.5)
print(str(x)+'\r',end='')
A resposta aceita não é perfeita . A linha que foi impressa primeiro permanecerá lá e se a segunda impressão não cobrir toda a nova linha, você acabará com o texto lixo.
Para ilustrar o problema, salve este código como um script e execute-o (ou apenas dê uma olhada):
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))
A saída será semelhante a esta:
Progress 0.0%%
Progress 1.0%%
Progress 2.0%%
Progress 3.0%%
O que funciona para mim é limpar a linha antes de deixar uma impressão permanente. Sinta-se à vontade para se ajustar ao seu problema específico:
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
E agora ele imprime conforme o esperado:
Progress 0.0%
Progress 1.0%
Progress 2.0%
Progress 3.0%
Aqui está uma versão mais limpa e "plug-and-play" da resposta de @ Nagasaki45. Ao contrário de muitas outras respostas aqui, ele funciona corretamente com strings de comprimentos diferentes. Ele consegue isso limpando a linha com tantos espaços quanto o comprimento da impressão da última linha. Também funcionará no 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
Basta usá-lo assim:
for msg in ["Initializing...", "Initialization successful!"]:
print_statusline(msg)
time.sleep(1)
Este pequeno teste mostra que as linhas são eliminadas corretamente, mesmo para comprimentos diferentes:
for i in range(9, 0, -1):
print_statusline("{}".format(i) * i)
time.sleep(0.5)
Estou um pouco surpreso por ninguém estar usando o caractere de retrocesso. Aqui está um que o usa.
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()
(Python3) Isso é o que funcionou para mim. Se você apenas usar o \ 010, ele deixará caracteres, então eu ajustei um pouco para ter certeza de que está substituindo o que estava lá. Isso também permite que você tenha algo antes do primeiro item de impressão e apenas remova o comprimento do item.
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
Mais uma resposta com base nas respostas anteriores.
Conteúdo de 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()
Uso do script:
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)
Aqui está minha solução! Windows 10, Python 3.7.1
Não sei por que esse código funciona, mas apaga completamente a linha original. Compilei com base nas respostas anteriores. As outras respostas apenas retornariam a linha ao início, mas se você tivesse uma linha mais curta depois, pareceria bagunçada como se hellotransforma em 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)
Saída - Cada linha será reescrita sem qualquer texto antigo mostrando:
SCRAPING COMPLETE: selenagomez
Próxima linha (completamente reescrita na mesma linha):
SCRAPING COMPLETE: beyonce
Melhor substituir toda a linha, caso contrário, a nova linha se misturará com as antigas se a nova linha for mais curta.
import time, os
for s in ['overwrite!', 'the!', 'whole!', 'line!']:
print(s.ljust(os.get_terminal_size().columns - 1), end="\r")
time.sleep(1)
Tive que usar columns - 1no Windows.