múltiples impresiones en la misma línea en Python

229

Quiero ejecutar un script, que básicamente muestra una salida como esta:

Installing XXX...               [DONE]

Actualmente, imprimo Installing XXX...primero y luego imprimo [DONE].

Sin embargo, ahora quiero imprimir Installing xxx...y [DONE]en la misma línea.

¿Algunas ideas?

usuario697108
fuente
1
Las respuestas a esta pregunta no mencionan que a veces desea borrar la línea, consulte: stackoverflow.com/questions/45263205
ideasman42

Respuestas:

284

Puede usar la printdeclaración para hacer esto sin importar sys.

def install_xxx():
   print "Installing XXX...      ",

install_xxx()
print "[DONE]"

La coma al final de la printlínea evita la printemisión de una nueva línea (debe tener en cuenta que habrá un espacio adicional al final de la salida).

La solución Python 3
Dado que lo anterior no funciona en Python 3, puede hacerlo en su lugar (nuevamente, sin importar sys):

def install_xxx():
    print("Installing XXX...      ", end="", flush=True)

install_xxx()
print("[DONE]")

La función de impresión acepta un endparámetro predeterminado "\n". Establecerlo en una cadena vacía evita que emita una nueva línea al final de la línea.

múltiples interfaces
fuente
1
Funciona perfectamente Solo había visto soluciones estándar hasta ahora. Muy bueno saber eso.
Prometeo
55
Esto no funciona si tiene ambas impresiones y una acción intermedia que requiere mucho tiempo (todas en la misma función / nivel de sangría). Antes de que comience la acción, no hay salida en absoluto y después de que termine, la salida aparece como un todo
Paddre
2
Probablemente sea más una función del almacenamiento en búfer de salida realizado por el sistema operativo para el proceso en su conjunto, que no es un problema específico de Python. Consulte stackoverflow.com/questions/107705 para obtener una solución específica para Python.
múltiples
13
Sin una nueva línea, probablemente desee vaciar explícitamente el búfer. Usar print("...", end="", flush=True)en Python 3, en Python 2 agregar una sys.stdout.flush()llamada.
Martijn Pieters
77
en python 3.x querrás agregar un "\ r" al final para reemplazar la línea impresa VS que se agrega al finalprint("Progress: {}%".format(var), end="\r", flush=True)
John
103

Simplemente puede usar esto:

print 'something',
...
print ' else',

y la salida será

something else

no hay necesidad de exagerar import sys. Presta atención al símbolo de coma al final.

Python 3+ print("some string", end=""); para eliminar la inserción de nueva línea al final. Leer más porhelp(print);

boldnik
fuente
3
Tenga en cuenta que hay dos espacios al usar este método
ethanjyx
1
Esta es la respuesta más simple y más eficiente.
gixxer
Esto no funciona cuando los argumentos de impresión están entre paréntesis. Esto funciona: <print "hola"; print ("hola")> pero esto no funciona <print ("hola",); print ("hola")>
Mayank Jaiswal
@MayankJaiswal Esto funciona con los padres. print ('hola'),
drglove
1
printla función tiene una sintaxis ligeramente diferente en python 2 VS 3.
boldnik
52

Debe usar la tecla de retroceso ' \ r ' o (' \ x08 ') char para volver a la posición anterior en la salida de la consola

Python 2+:

import time
import sys

def backspace(n):
    sys.stdout.write((b'\x08' * n).decode()) # use \x08 char to go back   

for i in range(101):                        # for 0 to 100
    s = str(i) + '%'                        # string for output
    sys.stdout.write(s)                     # just print
    sys.stdout.flush()                      # needed for flush when using \x08
    backspace(len(s))                       # back n chars    
    time.sleep(0.2)                         # sleep for 200ms

Python 3:

import time   

def backline():        
    print('\r', end='')                     # use '\r' to go back


for i in range(101):                        # for 0 to 100
    s = str(i) + '%'                        # string for output
    print(s, end='')                        # just print and flush
    backline()                              # back to the beginning of line    
    time.sleep(0.2)                         # sleep for 200ms

Este código contará del 0% al 100% en una línea. El valor final será:

> python test.py
100%

Información adicional sobre flush en este caso aquí: ¿Por qué las declaraciones de impresión de Python que contienen argumentos 'end =' se comportan de manera diferente en los bucles while?

Vadim Zin4uk
fuente
1
Para aclarar, parece que el código comentado en este ejemplo es para Python 2, y las líneas no comentadas son para Python 3.
tortugas son lindas
1
las líneas bucales funcionarán bien en Python 3. Si usa '\ x08' como retroceso, necesita vaciar el flujo de salida: print ((b '\ x08' * n) .decode (), end = '', flush = Es cierto)
Vadim Zin4uk
1
El retorno de carro '\ r' vuelve al principio de la línea, por lo que el '* n' es innecesario
bjnortier
43

Uso sys.stdout.write('Installing XXX... ')y sys.stdout.write('Done'). De esta manera, debe agregar la nueva línea a mano "\n"si desea recrear la funcionalidad de impresión. Creo que podría ser innecesario usar maldiciones solo por esto.

ferostar
fuente
44
Personalmente, prefiero esta solución a la más votada porque funciona exactamente de la misma manera en python2.xy python3.x sin necesidad de depender de las __future__importaciones ni nada de eso.
mgilson
17

Ninguna de las respuestas funcionó para mí, ya que todas se detuvieron hasta que se encontró una nueva línea. Escribí un simple ayudante:

def print_no_newline(string):
    import sys
    sys.stdout.write(string)
    sys.stdout.flush()

Para probarlo:

import time
print_no_newline('hello ')
# Simulate a long task
time.sleep(2)
print('world')

"hola" primero se imprimirá y se descargará en la pantalla antes de dormir. Después de eso, puede usar la impresión estándar.

hyprnick
fuente
1
¡Gracias! Exactamente lo que necesitaba también conocido como .flush ()
MrNice
11

Más sencillo:

Python 3

    print('\r' + 'something to be override', end='')

Significa que retrocederá el cursor al principio, que imprimirá algo y terminará en la misma línea. Si en un bucle comenzará a imprimir en el mismo lugar donde comienza.

Sunfloro
fuente
3
¡Frio! Funciona en Windows también.
Shital Shah
2
¡Gracias, esto funciona bien para mí! Sin print(’something to be override’, end=‘\r’)embargo, creo que eso es más simple.
Tropilio
9

Este simple ejemplo imprimirá 1-10 en la misma línea.

for i in range(1,11):
    print (i, end=" ")
Umali Leonard
fuente
9

La impresión tiene un endargumento opcional , es lo que se imprime al final. El valor predeterminado es una nueva línea, pero puede cambiarlo a una cadena vacía. p.ejprint("hello world!", end="")

TulkinRB
fuente
2
Esto está en Python 3. En Python 2 puedes simplemente print 'something',. La coma al final evita la adición de una nueva línea.
Arjoonn
4

Si desea sobrescribir la línea anterior (en lugar de continuamente añadiendo a la misma), se pueden combinar \rcon print(),al final de la instrucción de impresión. Por ejemplo,

from time import sleep

for i in xrange(0, 10):
    print("\r{0}".format(i)),
    sleep(.5)

print("...DONE!")

contará de 0 a 9, reemplazando el número anterior en la consola. Se "...DONE!"imprimirá en la misma línea que el último contador, 9.

En su caso para el OP, esto permitiría que la consola muestre el porcentaje completo de la instalación como una "barra de progreso", donde puede definir una posición de inicio y fin del personaje, y actualizar los marcadores intermedios.

print("Installing |XXXXXX              | 30%"),
Brian Bunker
fuente
4

Aquí una versión compatible con 2.7 derivada de la versión 3.0 de @ Vadim-Zin4uk:

Python 2

import time

for i in range(101):                        # for 0 to 100
    s = str(i) + '%'                        # string for output
    print '{0}\r'.format(s),                # just print and flush

    time.sleep(0.2)

Para el caso, la solución 3.0 proporcionada se ve un poco hinchada. Por ejemplo, el método de retroceso no utiliza el argumento entero y probablemente podría eliminarse por completo.

Python 3

import time

for i in range(101):                        # for 0 to 100
    s = str(i) + '%'                        # string for output
    print('{0}\r'.format(s), end='')        # just print and flush

    time.sleep(0.2)                         # sleep for 200ms

Ambos han sido probados y funcionan.

Dannid
fuente
2

Este es un hilo muy antiguo, pero aquí hay una respuesta muy completa y un código de muestra.

\res la representación de cadena del retorno de carro del juego de caracteres ASCII. Es lo mismo que octal 015[ chr(0o15)] o hexadecimal 0d[ chr(0x0d)] o decimal 13[ chr(13)]. Ver man asciipara una lectura aburrida. It ( \r) es una representación bastante portátil y es lo suficientemente fácil de leer para las personas. Simplemente significa mover el carro en la máquina de escribir hasta el inicio sin avanzar el papel. Es la CRparte de lo CRLFque significa retorno de carro y avance de línea .

print()es una función en Python 3. En Python 2 (cualquier versión que le interese usar), printpuede forzarse a una función importando su definición desde el __future__módulo. El beneficio de la printfunción es que puede especificar qué imprimir al final, anulando el comportamiento predeterminado de \nimprimir una nueva línea al final de cada print()llamada.

sys.stdout.flushle dice a Python que vacíe la salida de la salida estándar , que es donde envía la salida a print()menos que especifique lo contrario. También puede obtener el mismo comportamiento ejecutando python -uo configurando la variable de entorno PYTHONUNBUFFERED=1, omitiendo así las llamadas import sysy sys.stdout.flush(). La cantidad que gana al hacer eso es casi exactamente cero y no es muy fácil de depurar si olvida convenientemente que tiene que hacer ese paso antes de que su aplicación funcione correctamente.

Y una muestra. Tenga en cuenta que esto funciona perfectamente en Python 2 o 3.

from __future__ import print_function

import sys
import time

ANS = 42
FACTORS = {n for n in range(1, ANS + 1) if ANS % n == 0}

for i in range(1, ANS + 1):
    if i in FACTORS:
        print('\r{0:d}'.format(i), end='')
        sys.stdout.flush()
        time.sleep(ANS / 100.0)
else:
    print()
Chris Cosby
fuente
Creo que su respuesta es más adecuada para: stackoverflow.com/questions/45263205/…
Marc Cayuela Rafols
2

print () tiene un parámetro incorporado "end" que está configurado de forma predeterminada en "\ n" Llamar a print ("This is America") en realidad llama a print ("This is America", end = "\ n"). Una manera fácil de hacerlo es llamar a print ("This is America", end = "")

Miles Mbo
fuente
1

En caso de que haya almacenado previamente los valores en una matriz, puede llamarlos en el siguiente formato:

for i in range(0,n):
       print arr[i],
k20392
fuente
1

Python agrega nueva línea como un final para imprimir. Use end = '' para python3 para el método de impresión para agregar un espacio en lugar de una nueva línea. para python2 use una coma al final de la declaración de impresión.

print("Foo",end=' ')
print('Bar')
MrKulli
fuente
0

Encontré esta publicación de Quora , con este ejemplo que funcionó para mí (python 3), que estaba más cerca de lo que necesitaba (es decir, borrar toda la línea anterior).

El ejemplo que brindan:

def clock():
   while True:
       print(datetime.now().strftime("%H:%M:%S"), end="\r")

Para imprimir en la misma línea, como han sugerido otros, simplemente use end=""

Mircea
fuente
-2

Encontré esta solución y está funcionando en Python 2.7

# Working on Python 2.7 Linux

import time
import sys


def backspace(n):
    print('\r', end='')                     # use '\r' to go back


for i in range(101):                        # for 0 to 100
    s = str(i) + '%'                        # string for output
    sys.stdout.write(string)
    backspace(len(s))                       # back for n chars
    sys.stdout.flush()
    time.sleep(0.2)                         # sleep for 200ms
Luis Silva
fuente
1
Esa printes una sintaxis incorrecta para Python 2.7 y el código no funciona incluso con la sintaxis correcta.
Cory Madden