Come posso scrivere l'output nello stesso posto sulla console?


158

Sono nuovo di Python e sto scrivendo alcuni script per automatizzare il download di file da server FTP, ecc. Voglio mostrare l'avanzamento del download, ma voglio che rimanga nella stessa posizione, come:

produzione:

Download del file FooFile.txt [47%]

Sto cercando di evitare qualcosa del genere:

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

Come devo fare per fare questo?


Duplica : come posso stampare sulla riga corrente in un'applicazione a riga di comando?


1
potresti essere interessato a questo modulo facile da usare, è una barra di avanzamento del testo. pypi.python.org/pypi/progressbar/2.2
wim

Risposte:


254

Puoi anche utilizzare il ritorno a capo:

sys.stdout.write("Download progress: %d%%   \r" % (progress) )
sys.stdout.flush()

13
Soluzione molto comune e semplice. Nota: se la linea è più lunga della larghezza del terminale, diventa brutta.
effimero

5
Ho anche dovuto aggiungere una chiamata a sys.stdout.flush () in modo che il cursore non rimbalzasse
scottm,

19
È possibile farlo con più righe? Diciamo che ho tre download diversi e voglio mostrare l'avanzamento di ciascuno sulla propria linea.
EarlCrapstone

11
Mi piace mettere \rall'inizio della riga e aggiungere a \x1b[Kper cancellare il testo precedente.
Augurar

11
Sembra che la soluzione più semplice per Python 3 (come menzionato nelle risposte seguenti) sia: print("sample text", end='\r", flush=True)
Ciro

35

Python 2

Mi piace quanto segue:

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

demo:

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

demo:

import time

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

PyCharm Debugger Console 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.')

9
usa questo per python 3+: print ('Download del file FooFile.txt [% d %%] \ r'% i, end = "")
hkoosha,

Sulla console del debugger di PyCharm, deve venire prima del testo. Altrimenti, il testo potrebbe non apparire affatto o apparire in modo incoerente. Ho aggiunto la versione che funziona per me come una modifica, perché non ho potuto scrivere codice multilinea in questa risposta. L'ho messo sul mio succo in modo che le persone possano vederlo mentre la modifica è in attesa di approvazione: gist.github.com/yulkang/40168c7729a7a7b96d0116d8b1bc26df
Yul Kang

"\ r" alla fine della stringa funziona per me nella console di debugger su PyCharm 2020.1 (PyCharm 2020.1.2 (Community Edition); Build # PC-201.7846.77, costruito il 31 maggio 2020).
battey l'


15

Stampa il carattere backspace \bpiù volte, quindi sovrascrivi il vecchio numero con il nuovo numero.


interessante, non avevo pensato di farlo in quel modo.
Chris Ballance,

Mi piace perché non cancella i comandi precedenti (se hai più livelli che vuoi lasciare sullo schermo)
Nathan Donnellan,

3
L'uso del ritorno print 'Downloading.... \r'a capo (ad es. ) Non cancella anche i dati precedenti, ma impedisce di sapere fino a che punto eseguire il backup.
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="")

Perché è meglio di quanto sopra (sono un Python n00b, quindi per favore scusa la mia ignoranza :-))?
BalinKingOfMoria Ripristina CM

7

Per Python 3xx:

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

4

Una soluzione chiara che ha funzionato per me è:

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

Il sys.stdout.flushè importante altrimenti si fa veramente goffo e l' print("")on per l'uscita ad anello è anche importante.

AGGIORNAMENTO : Come menzionato nei commenti, printha anche un flushargomento. Quindi funzionerà anche:

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

1
In Python moderna, è possibile fornire un ARG di flush=Truea print, quindi non c'è alcuna necessità per l'extra sys.stdout.flush()chiamata.
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="")
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.