¿Cómo sobrescribir la impresión anterior a stdout en python?

Si tuviera el siguiente código:

for x in range(10): print x 

Obtendría la salida de

 1 2 etc.. 

Lo que me gustaría hacer es que, en lugar de imprimir una nueva línea, deseo reemplazar el valor anterior y sobrescribirlo con el nuevo valor en la misma línea.

Una forma es usar el carácter de retorno de carro ( '\r' ) para regresar al inicio de la línea sin avanzar a la siguiente línea:

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

La coma al final de la statement de impresión le dice que no pase a la siguiente línea. La última statement de impresión avanza a la siguiente línea para que su solicitud no sobrescriba su salida final.

Desde que terminé aquí a través de Google, pero estoy usando Python 3, así es como funcionaría en Python 3:

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

Respuesta relacionada aquí: ¿Cómo puedo suprimir la nueva línea después de una statement de impresión?

La respuesta de @Mike DeSimone probablemente funcionará la mayor parte del tiempo. Pero…

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

Esto se debe a que '\r' solo vuelve al principio de la línea pero no borra la salida.

EDITAR: Mejor solución (que mi antigua propuesta a continuación)

Si la compatibilidad con POSIX es suficiente para usted, lo siguiente borraría la línea actual y dejaría el cursor al principio:

 print '\x1b[2K\r', 

Utiliza el código de escape ANSI para despejar la línea del terminal. Más información se puede encontrar en Wikipedia y en esta gran charla .

Vieja respuesta

La solución (no tan buena) que he encontrado se ve así:

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

Una ventaja es que también funcionará en Windows.

Tuve la misma pregunta antes de visitar este hilo. Para mí, sys.stdout.write funcionó solo si descargo el búfer correctamente, es decir,

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

Sin vaciar, el resultado se imprime solo al final del guión.

Suprimir la nueva línea e imprimir.

 print 1, print '\r2' 

o escribir a stdout:

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

No pude conseguir que ninguna de las soluciones en esta página funcionara para IPython , pero una pequeña variación en la solución de @ Mike-Desimone hizo el trabajo: en lugar de terminar la línea con el retorno de carro, comience la línea con el retorno de carro:

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

Además, este enfoque no requiere la segunda statement de impresión.

Prueba esto:

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

Funciono para mi La parte end="\r" hace que se sobrescriba la línea anterior.

¡ADVERTENCIA!

Si imprime hi , luego imprima hello usando \r , obtendrá hillo porque la salida se escribió sobre las dos letras anteriores. Si imprime hi con espacios (que no se muestran aquí), saldrá hi . Para arreglar esto, imprima espacios usando \r .

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

time.sleep (0.5) es para mostrar cómo se borra la salida anterior y la nueva salida se imprime “\ r” cuando está al comienzo del mensaje de impresión, borrará la salida anterior antes de la nueva salida.

La respuesta aceptada no es perfecta . La línea que se imprimió primero permanecerá allí y si su segunda impresión no cubre toda la nueva línea, terminará con texto basura.

Para ilustrar el problema, guarde este código como un script y ejecútelo (o simplemente eche un vistazo):

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

La salida se verá algo como esto:

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

Lo que me funciona es despejar la línea antes de dejar una impresión permanente. Siéntase libre de adaptarse a su 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 

Y ahora se imprime como se espera:

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

He usado lo siguiente para crear un cargador:

 for i in range(10): print(i*'.', end='\r') 

Esto funciona en Windows y Python 3.6

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

Una versión más limpia, más “plug-and-play”, a la respuesta de @ Nagasaki45:

 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 # Then simply use like this: for msg in ["Initializing...", "Initialization successful!"]: print_statusline(msg) time.sleep(1) # If you want to check that the line gets cleared properly: for i in range(9, 0, -1): print_statusline("{}".format(i) * i) time.sleep(0.5) 

Funciona correctamente con cadenas de diferentes longitudes, ya que despeja la línea con espacios, a diferencia de muchas otras respuestas aquí. También funcionará en Windows.

Estoy un poco sorprendido de que nadie esté usando el carácter de retroceso. Aquí hay uno que lo 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') 

¡Aquí está mi solución! Windows 10, Python 3.7.1

No estoy seguro de por qué funciona este código, pero borra completamente la línea original. Lo compilé de las respuestas anteriores. Las otras respuestas solo devolverían la línea al principio, pero si tuvieras una línea más corta después, se vería desordenada como si hello se byelo en 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) 

Salida: cada línea se volverá a escribir sin ningún texto antiguo que muestre:

 SCRAPING COMPLETE: selenagomez 

Siguiente línea (reescrita completamente en la misma línea):

 SCRAPING COMPLETE: beyonce 

Aquí un código simple que puede ser útil para usted!

 import sys import time for i in range(10): sys.stdout.write("\r" + i) sys.stdout.flush() time.sleep(1)