Comment écrire la sortie au même endroit sur la console?


158

Je suis nouveau sur python et j'écris des scripts pour automatiser le téléchargement de fichiers à partir de serveurs FTP, etc. Je veux montrer la progression du téléchargement, mais je veux qu'il reste dans la même position, comme:

production:

Téléchargement du fichier FooFile.txt [47%]

J'essaye d'éviter quelque chose comme ça:

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

Comment dois-je procéder?


Dupliquer : Comment puis-je imprimer sur la ligne actuelle dans une application de ligne de commande?


1
vous pourriez être intéressé par ce module facile à utiliser, c'est une barre de progression de texte. pypi.python.org/pypi/progressbar/2.2
wim

Réponses:


254

Vous pouvez également utiliser le retour chariot:

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

13
Solution très courante et simple. Remarque: si votre ligne est plus longue que la largeur de votre terminal, cela devient moche.
éphémère le

5
J'ai également dû ajouter un appel à sys.stdout.flush () pour que le curseur ne rebondisse pas
scottm

19
Est-il possible de faire cela avec plusieurs lignes? Disons que j'ai trois téléchargements différents, et je veux montrer la progression de chacun sur sa propre ligne.
EarlCrapstone

11
J'aime mettre le \rau début de la ligne et ajouter un \x1b[Kpour effacer le texte précédent.
augurar

11
Il semble que la solution la plus simple pour python 3 (comme mentionné dans les réponses ci-dessous) soit: print("sample text", end='\r", flush=True)
Cyrus

35

Python 2

J'aime ce qui suit:

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

Démo:

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

Démo:

import time

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

Console de débogage PyCharm avec 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
utilisez ceci pour python 3+: print ('Téléchargement du fichier FooFile.txt [% d %%] \ r'% i, end = "")
hkoosha

Sur la console PyCharm Debugger, \ r doit venir avant le texte. Sinon, le texte peut ne pas apparaître du tout ou apparaître de manière incohérente. J'ai ajouté la version qui fonctionne pour moi en tant que modification, car je ne pouvais pas écrire de code multiligne dans cette réponse. Je l'ai mis sur mon essentiel pour que les gens puissent le voir pendant que la modification est en attente d'approbation: gist.github.com/yulkang/40168c7729a7a7b96d0116d8b1bc26df
Yul Kang

"\ r" à la fin de la chaîne fonctionne pour moi dans la console de débogage sur PyCharm 2020.1 (PyCharm 2020.1.2 (Community Edition); Build # PC-201.7846.77, construit le 31 mai 2020).
battey


15

Imprimez \bplusieurs fois le caractère de retour arrière , puis remplacez l'ancien numéro par le nouveau.


intéressant, je n'avais pas pensé à le faire de cette façon.
Chris Ballance

J'aime cela car cela n'efface pas les commandes précédentes (si vous avez plusieurs étapes que vous souhaitez laisser à l'écran)
Nathan Donnellan

3
L'utilisation du retour chariot (par exemple print 'Downloading.... \r') n'efface pas non plus les données précédentes, mais évite d'avoir à savoir jusqu'où sauvegarder.
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="")

Pourquoi est-ce mieux que ce qui précède (je suis un Python n00b, alors veuillez excuser mon ignorance :-))?
BalinKingOfMoria réintègre les CM

7

Pour Python 3xx:

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

4

Une solution intéressante qui a fonctionné pour moi est:

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

Le sys.stdout.flushest important sinon il devient vraiment maladroit et la print("")sortie de la boucle on for est également importante.

MISE À JOUR : Comme mentionné dans les commentaires, a printégalement un flushargument. Donc, ce qui suit fonctionnera également:

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
Dans Python moderne, vous pouvez fournir un argument de flush=Trueto print, donc il n'y a pas besoin d'un sys.stdout.flush()appel supplémentaire .
PM 2 Ring

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="")
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.