2009-01-21 10 views
15

Sous Unix, je peux utiliser \ r (retour chariot) ou \ b (retour arrière) pour imprimer sur du texte déjà visible dans le shell (c'est-à-dire remplacer à nouveau la ligne en cours). Est-ce que je peux obtenir le même effet dans une ligne de commande Windows à partir d'un script Python?Comment imprimer sur la ligne en cours dans une application de ligne de commande?

J'ai essayé le module curses mais il ne semble pas être disponible sous Windows.

+0

Ma [question] (http://stackoverflow.com/questions/51212/how-to-write-a-download-progress-indicator-in-python) au sujet d'un Python Télécharger L'indicateur de progression pourrait être utile. – cschol

Répondre

23

oui:

import sys 
import time 

def restart_line(): 
    sys.stdout.write('\r') 
    sys.stdout.flush() 

sys.stdout.write('some data') 
sys.stdout.flush() 
time.sleep(2) # wait 2 seconds... 
restart_line() 
sys.stdout.write('other different data') 
sys.stdout.flush() 
+0

génial, pour ceux qui se demandent: fonctionne avec 2.7 –

+3

Si la deuxième donnée est plus courte que la première, les premiers caractères de données sont laissés sur la console – Hilal

2

façon simple si vous êtes juste vouloir mettre à jour la ligne précédente:

import time 
for i in range(20): 
    print str(i) + '\r', 
    time.sleep(1) 
1

Sous Windows (python 3), il semble fonctionner (ne pas utiliser directement stdout):

import sys 

for i in reversed(range(0,20)): 
    time.sleep(0.1) 
    if(i == 19): 
    print(str(i), end='', file=sys.stdout) 
    else: 
    print("\r{0:{width}".format(str(i), width = w, fill = ' ', align = 'right'), end='', file=sys.stdout) 
    sys.stdout.flush() 
    w = len(str(i)) 

La même ligne est mise à jour à chaque fois que la fonction d'impression est appelée.

Cet algorithme peut être amélioré, mais il est affiché pour montrer ce que vous pouvez faire. Vous pouvez modifier la méthode en fonction de vos besoins.

11
import sys 
import time 

for i in range(10): 
    print '\r',   # print is Ok, and comma is needed. 
    time.sleep(0.3) 
    print i, 
    sys.stdout.flush() # flush is needed. 

Et si sur le IPython-ordinateur portable, comme ceci:

import time 
from IPython.display import clear_output 

for i in range(10): 
    time.sleep(0.25) 
    print(i) 
    clear_output(wait=True) 

http://nbviewer.ipython.org/github/ipython/ipython/blob/master/examples/notebooks/Animations%20Using%20clear_output.ipynb

+1

ipython notebook/jupyter est ce que je cherchais! – dmeu

4

Je sais que c'est vieux, mais je voulais dire ma version (il fonctionne sur mon PC dans le cmd, mais pas dans le ralenti) pour remplacer une ligne python 3:

>>> from time import sleep 
>>> for i in range(400): 
>>>  print("\r" + str(i), end="") 
>>>  sleep(0.5) 

EDIT: Cela fonctionne sur Windows et sur Ubuntu

5

J'ai juste eu ce problème. Vous pouvez toujours utiliser \r, même dans Windows Invite de commandes, cependant, il vous ramène uniquement au saut de ligne précédent (\n).

Si vous faites quelque chose comme ceci:

cnt = 0 
print str(cnt) 
while True: 
    cnt += 1 
    print "\r" + str(cnt) 

Vous obtiendrez:

0 
1 
2 
3 
4 
5 
... 

C'est parce que \r ne remonte à la dernière ligne. Puisque vous avez déjà écrit un caractère de nouvelle ligne avec la dernière instruction d'impression, votre curseur va du début d'une nouvelle ligne vide au début de la même nouvelle ligne vide.

Pour illustrer, après avoir imprimé le premier 0, votre curseur serait ici:

0 
| # <-- Cursor 

Lorsque vous \r, vous allez au début de la ligne. Mais vous êtes déjà au début de la ligne.La solution est d'éviter d'imprimer un caractère \n, donc votre curseur est sur la même ligne et \r écrase le texte correctement. Vous pouvez le faire avec print 'text',. La virgule empêche l'impression d'un caractère de nouvelle ligne.

cnt = 0 
print str(cnt), 
while True: 
    cnt += 1 
    print "\r" + str(cnt), 

Maintenant, il va correctement réécrire les lignes. Notez que c'est Python 2.7, d'où les instructions print.

5

méthode simple :)

import sys 
from time import sleep 
import os 

#print("\033[y coordinate;[x coordinateH Hello") 
os.system('cls') 
sleep(0.2) 
print("\033[1;1H[]") 
sleep(0.2) 
print("\033[1;1H []") 
sleep(0.2) 
print("\033[1;1H []") 
sleep(0.2) 
print("\033[1;1H  []") 
sleep(0.2) 
print("\033[1;1H  []") 
sleep(0.2) 
print("\033[1;1H  []") 
sleep(0.2) 
print("\033[1;1H []") 
sleep(0.2) 
print("\033[1;1H []") 
sleep(0.2) 
print("\033[1;1H[]") 
sleep(0.2) 
0

Merci pour toutes les réponses utiles ici les gars. J'avais besoin de ceci :)

J'ai trouvé la réponse de nosklo particulièrement utile, mais je voulais quelque chose de complètement contenu dans une fonction en passant la sortie désirée en tant que paramètre. De plus, je n'avais pas vraiment besoin de la minuterie, puisque je voulais que l'impression ait lieu après un événement spécifique).

C'est ce qui a fait l'affaire pour moi, j'espère que quelqu'un d'autre trouve utile:

import sys 

def replace_cmd_line(output): 
    """Replace the last command line output with the given output.""" 
    sys.stdout.write(output) 
    sys.stdout.flush() 
    sys.stdout.write('\r') 
    sys.stdout.flush() 
+0

Vous n'avez besoin que d'un seul flush() à la fin. Je ne suis pas sûr que 'sys.stdout.write (output + '\ r')' serait plus rapide que deux appels de méthode (à cause de l'allocation de mémoire pour la chaîne, la copie, GC), donc les garder séparés est probablement OK . –

1

manière la plus simple est d'utiliser deux \ r - un au début et à la fin

for i in range(10000): 
    print('\r'+str(round(i*100/10000))+'% Complete\r'), 

Il va très vite

+0

: -/Le premier '\ r' sera traité 9999 fois pour rien. Si vous ne savez pas où se trouve votre curseur, vous pouvez appeler 'print ('\ r')' * une fois * avant la boucle. –

Questions connexes