¿Cómo escribo la salida en el mismo lugar en la consola?

158

Soy nuevo en Python y estoy escribiendo algunos scripts para automatizar la descarga de archivos desde servidores FTP, etc. Quiero mostrar el progreso de la descarga, pero quiero que permanezca en la misma posición, como:

salida:

Descargando el archivo FooFile.txt [47%]

Estoy tratando de evitar algo como esto:

     Downloading File FooFile.txt [47%]
     Downloading File FooFile.txt [48%]
     Downloading File FooFile.txt [49%]

¿Cómo debo hacer esto?


Duplicado : ¿Cómo puedo imprimir sobre la línea actual en una aplicación de línea de comando?

scottm
fuente
1
Quizás te interese este módulo fácil de usar, es una barra de progreso de texto. pypi.python.org/pypi/progressbar/2.2
wim

Respuestas:

254

También puede usar el retorno de carro:

sys.stdout.write("Download progress: %d%%   \r" % (progress) )
sys.stdout.flush()
codelogic
fuente
13
Solución muy común y simple. Nota: si su línea es más larga que el ancho de su terminal, esto se pone feo.
ephemient
55
También tuve que agregar una llamada a sys.stdout.flush () para que el cursor no rebotara
scottm
19
¿Es posible hacer esto con varias líneas? Digamos que tengo tres descargas diferentes, y quiero mostrar el progreso de cada una en su propia línea.
EarlCrapstone
11
Me gusta poner el \ral principio de la línea y agregar un \x1b[Kpara borrar el texto anterior.
augurar
11
Parece que la solución más simple para Python 3 (como se menciona en las respuestas a continuación) es: print("sample text", end='\r", flush=True)
Cyrus
35

Python 2

Me gusta lo siguiente:

print 'Downloading File FooFile.txt [%d%%]\r'%i,

Manifestación:

import time

for i in range(100):
    time.sleep(0.1)
    print 'Downloading File FooFile.txt [%d%%]\r'%i,

Python 3

print('Downloading File FooFile.txt [%d%%]\r'%i, end="")

Manifestación:

import time

for i in range(100):
    time.sleep(0.1)
    print('Downloading File FooFile.txt [%d%%]\r'%i, end="")

Consola de depurador PyCharm con Python 3

# On PyCharm Debugger console, \r needs to come before the text.
# Otherwise, the text may not appear at all, or appear inconsistently.
# tested on PyCharm 2019.3, Python 3.6

import time

print('Start.')
for i in range(100):
    time.sleep(0.02)
    print('\rDownloading File FooFile.txt [%d%%]'%i, end="")
print('\nDone.')
RSabet
fuente
9
use esto para python 3+: print ('Descargando el archivo FooFile.txt [% d %%] \ r'% i, end = "")
hkoosha
En la consola de PyCharm Debugger, debe aparecer antes del texto. De lo contrario, el texto puede no aparecer en absoluto, o aparecer de manera inconsistente. Agregué la versión que funciona para mí como edición, porque no pude escribir código de varias líneas en esta respuesta. Lo puse en mi esencia para que la gente pueda verlo mientras la edición está esperando aprobación: gist.github.com/yulkang/40168c7729a7a7b96d0116d8b1bc26df
Yul Kang
"\ r" al final de la cadena me funciona en la consola del depurador en PyCharm 2020.1 (PyCharm 2020.1.2 (Community Edition); Build # PC-201.7846.77, construido el 31 de mayo de 2020).
Battey
28

Use una biblioteca de manejo de terminales como el módulo curses :

El módulo curses proporciona una interfaz con la biblioteca curses, el estándar de facto para el manejo avanzado de terminales portátiles.

gimel
fuente
1
No disponible para Windows.
Diego Herranz
3
@Diego ahora hay una biblioteca de soporte para el módulo curses en Windows. ver stackoverflow.com/a/19851287/1426237
Plexico
15

Imprima el carácter de retroceso \bvarias veces y luego sobrescriba el número anterior con el nuevo.

Zach Scrivena
fuente
interesante, no había pensado en hacerlo de esa manera.
Chris Ballance
Me gusta esto porque no borra los comandos anteriores (si tiene varias etapas que desea dejar en la pantalla)
Nathan Donnellan
3
El uso del retorno de carro (p print 'Downloading.... \r'. Ej. ) Tampoco borra los datos anteriores, pero evita tener que saber qué tan lejos se debe hacer una copia de seguridad.
cod3monk3y
8
#kinda like the one above but better :P

from __future__ import print_function
from time import sleep

for i in range(101):
  str1="Downloading File FooFile.txt [{}%]".format(i)
  back="\b"*len(str1)
  print(str1, end="")
  sleep(0.1)
  print(back, end="")
Christian Calderon
fuente
¿Por qué es esto mejor que lo anterior (soy Python n00b, así que disculpe mi ignorancia :-))?
BalinKingOfMoria Reinstale CMs
7

Para Python 3xx:

import time
for i in range(10):
    time.sleep(0.2) 
    print ("\r Loading... {}".format(i)+str(i), end="")
TheRutubeify
fuente
4

Una buena solución que me ha funcionado es:

from __future__ import print_function
import sys
for i in range(10**6):
    perc = float(i) / 10**6 * 100
    print(">>> Download is {}% complete      ".format(perc), end='\r')
    sys.stdout.flush()
print("")

El sys.stdout.flushes importante de lo contrario se pone muy torpe y el print("")de salida de bucle también es importante.

ACTUALIZACIÓN : Como se menciona en los comentarios, printtambién tiene un flushargumento. Entonces lo siguiente también funcionará:

from __future__ import print_function
for i in range(10**6):
    perc = float(i) / 10**6 * 100
    print(">>> Download is {}% complete      ".format(perc), end='\r', flush=True)
print("")
Michael Hall
fuente
1
En Python moderno, puede proporcionar un argumento de flush=Trueto print, por lo que no hay necesidad de una sys.stdout.flush()llamada adicional .
PM 2Ring
0
x="A Sting {}"
   for i in range(0,1000000):
y=list(x.format(i))
print(x.format(i),end="")

for j in range(0,len(y)):
    print("\b",end="")
Malayo hazarika
fuente