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?

Scottm
la source
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()
codelogic
la source
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.')
RSabet
la source
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
28

Utilisez une bibliothèque de gestion de terminaux comme le module curses :

Le module curses fournit une interface à la bibliothèque curses, le standard de facto pour la gestion avancée des terminaux portables.

gimel
la source
1
Non disponible pour Windows.
Diego Herranz
3
@Diego il y a maintenant une bibliothèque de support pour le module curses sur Windows. voir stackoverflow.com/a/19851287/1426237
Plexico
15

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

Zach Scrivena
la source
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="")
Christian Calderon
la source
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="")
TheRutubeify
la source
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("")
Michael Hall
la source
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="")
Malais Hazarika
la source