web-dev-qa-db-fra.com

Imprimer dynamiquement sur une ligne

Je voudrais faire plusieurs déclarations qui donnent une sortie standard sans voir de nouvelles lignes entre les instructions.

Spécifiquement, supposons que j'ai:

for item in range(1,100):
    print item

Le résultat est:

1
2
3
4
.
.
.

Comment obtenir cela à la place ressemble à:

1 2 3 4 5 ...

Mieux encore, est-il possible d'imprimer le numéro unique sur / le dernier numéro, de sorte qu'un seul numéro est affiché à l'écran à la fois?

255
Pol

Remplacez print item par:

  • print item, en Python 2.7
  • print(item, end=" ") en Python 3

Si vous souhaitez imprimer les données de manière dynamique, utilisez la syntaxe suivante:

  • print(item, sep=' ', end='', flush=True) en Python 3
421
ewall

Au fait ...... Comment l'actualiser à chaque fois pour qu'il s'imprime au même endroit, changez simplement le numéro.

En général, vous pouvez utiliser codes de contrôle de terminal . C'est un cas particulièrement simple, pour lequel vous n'avez besoin que d'un caractère spécial: U + 000D CARRIAGE RETURN, écrit '\r' en Python (et dans de nombreuses autres langues). Voici un exemple complet basé sur votre code:

from sys import stdout
from time import sleep
for i in range(1,20):
    stdout.write("\r%d" % i)
    stdout.flush()
    sleep(1)
stdout.write("\n") # move the cursor to the next line

Certaines choses à ce sujet peuvent être surprenantes:

  • Le \r se place au début de la chaîne de sorte que, pendant l'exécution du programme, le curseur sera toujours après le nombre. Ce n’est pas uniquement esthétique: certains émulateurs de terminaux deviennent très confus si vous le faites à l’inverse.
  • Si vous n'incluez pas la dernière ligne, votre Shell imprimera son invite au-dessus du numéro une fois le programme terminé.
  • Le stdout.flush est nécessaire sur certains systèmes, sinon vous n'obtiendrez aucune sortie. D'autres systèmes peuvent ne pas en avoir besoin, mais cela ne fait aucun mal.

Si vous constatez que cela ne fonctionne pas, la première chose à laquelle vous devriez vous attendre, c'est que votre émulateur de terminal est défectueux. Le programme vttest peut vous aider à le tester.

Vous pouvez remplacer le stdout.write par une instruction print mais je préfère ne pas associer print à une utilisation directe des objets de fichier.

141
zwol

Utilisez print item, pour que l'instruction print omette la nouvelle ligne.

En Python 3, c'est print(item, end=" ").

Si vous voulez que tous les nombres s'affichent au même endroit, utilisez par exemple (Python 2.7):

to = 20
digits = len(str(to - 1))
delete = "\b" * (digits + 1)
for i in range(to):
    print "{0}{1:{2}}".format(delete, i, digits),

En Python 3, c'est un peu plus compliqué. Ici, vous devez vider le sys.stdout ou il n’imprimera rien avant la fin de la boucle:

import sys
to = 20
digits = len(str(to - 1))
delete = "\b" * (digits)
for i in range(to):
   print("{0}{1:{2}}".format(delete, i, digits), end="")
   sys.stdout.flush()
47
Tim Pietzcker

Comme les autres exemples,
J'utilise une approche similaire, mais au lieu de passer du temps à calculer la dernière longueur de sortie, etc. 

J'utilise simplement des échappements de code ANSI pour revenir au début de la ligne, puis effacer toute cette ligne avant d'imprimer ma sortie d'état actuel.

import sys

class Printer():
    """Print things to stdout on one line dynamically"""
    def __init__(self,data):
        sys.stdout.write("\r\x1b[K"+data.__str__())
        sys.stdout.flush()

Pour l'utiliser dans votre boucle d'itération, vous appelez simplement quelque chose comme:

x = 1
for f in fileList:
    ProcessFile(f)
    output = "File number %d completed." % x
    Printer(output)
    x += 1   

Voir plus ici

16
Matthew

Vous pouvez ajouter une virgule de fin à votre instruction print pour imprimer un espace au lieu d'une nouvelle ligne à chaque itération:

print item,

Si vous utilisez Python 2.6 ou une version ultérieure, vous pouvez également utiliser la nouvelle fonction d'impression, ce qui vous permettrait d'indiquer qu'aucun espace ne devrait même venir à la fin de chaque élément en cours d'impression (ou vous permettre de spécifier le type de fin souhaité) vouloir):

from __future__ import print_function
...
print(item, end="")

Enfin, vous pouvez écrire directement sur la sortie standard en l'important à partir du module sys, qui renvoie un objet de type fichier:

from sys import stdout
...
stdout.write( str(item) )
14
Eli Courtwright

changement

print item

à

print "\033[K", item, "\r",
sys.stdout.flush()
  • "\ 033 [K" efface jusqu'à la fin de la ligne 
  • le\r, retourne au début de la ligne 
  • l'instruction flush s'assure qu'elle s'affiche immédiatement afin que vous obteniez une sortie en temps réel.
10
Brooks

Je pense qu'une simple jointure devrait fonctionner:

nl = []
for x in range(1,10):nl.append(str(x))
print ' '.join(nl)
5
xortion

"Au fait ...... Comment l'actualiser à chaque fois pour qu'il s'imprime au même endroit, il suffit de changer le numéro."

C'est un sujet vraiment délicat. Ce que zack a suggéré (générer les codes de contrôle de la console) est un moyen d’y parvenir.

Vous pouvez utiliser (n) curses, mais cela fonctionne principalement sur * nix.

Sur Windows (et ici une partie intéressante) qui est rarement mentionnée (je ne comprends pas pourquoi), vous pouvez utiliser les liaisons Python vers WinAPI ( http://sourceforge.net/projects/pywin32/ avec également ActivePython par défaut) ) - ce n'est pas si difficile et ça marche bien. Voici un petit exemple:

import win32console, time

output_handle = win32console.GetStdHandle(  win32console.STD_OUTPUT_HANDLE )
info = output_handle.GetConsoleScreenBufferInfo()
pos = info["CursorPosition"]

for i in "\\|/-\\|/-":
    output_handle.WriteConsoleOutputCharacter( i, pos )
    time.sleep( 1 )

Ou, si vous voulez utiliser print (instruction ou fonction, aucune différence):

import win32console, time

output_handle = win32console.GetStdHandle(  win32console.STD_OUTPUT_HANDLE )
info = output_handle.GetConsoleScreenBufferInfo()
pos = info["CursorPosition"]

for i in "\\|/-\\|/-":
    print i
    output_handle.SetConsoleCursorPosition( pos )
    time.sleep( 1 )

Le module win32console vous permet de faire beaucoup plus de choses intéressantes avec la console Windows ... Je ne suis pas un grand fan de WinAPI, mais je me suis récemment rendu compte qu'au moins la moitié de mon antipathie à son égard était due à l'écriture de code WinAPI dans les liaisons C-Pythonic sont beaucoup plus faciles à utiliser.

Toutes les autres réponses sont bonnes et Pythonic, bien sûr, mais ... Et si je voulais imprimer sur la ligne previous? Ou écrivez un texte multiligne, puis effacez-le et écrivez à nouveau les mêmes lignes? Ma solution rend cela possible.

3
cji

Une autre réponse que j'utilise sur 2.7 où je viens d'imprimer un "." Chaque fois qu'une boucle est exécutée (pour indiquer à l'utilisateur que des choses sont toujours en cours d'exécution), voici ceci:

print "\b.",

Il imprime le "." caractères sans espaces entre eux. Cela semble un peu mieux et fonctionne assez bien. Le\b est un caractère de retour arrière pour ceux qui s’interrogent.

3
copeland3300

Pour que les nombres se superposent, vous pouvez faire quelque chose comme ceci:

for i in range(1,100):
    print "\r",i,

Cela devrait fonctionner tant que le numéro est imprimé dans la première colonne.

EDIT: Voici une version qui fonctionnera même si elle n’est pas imprimée dans la première colonne.

prev_digits = -1
for i in range(0,1000):
    print("%s%d" % ("\b"*(prev_digits + 1), i)),
    prev_digits = len(str(i))

Je dois noter que ce code a été testé et fonctionne parfaitement dans Python 2.5 sous Windows, dans la console Windows. Selon certaines personnes, il peut être nécessaire de purger la stdout pour voir les résultats. YMMV.

2
Adam Crossland

pour Python 2.7

for x in range(0, 3):
    print x,

pour Python 3

for x in range(0, 3):
    print(x, end=" ")
1
Adnan Ghaffar
In [9]: print?
Type:           builtin_function_or_method
Base Class:     <type 'builtin_function_or_method'>
String Form:    <built-in function print>
Namespace:      Python builtin
Docstring:
    print(value, ..., sep=' ', end='\n', file=sys.stdout)

Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep:  string inserted between values, default a space.
end:  string appended after the last value, default a newline.
1
gtrak
for i in xrange(1,100):
  print i,
1
eruciform

En Python 3, vous pouvez le faire de cette façon:

for item in range(1,10):
    print(item, end =" ")

Les sorties:

1 2 3 4 5 6 7 8 9 

Tuple: / Vous pouvez faire la même chose avec un tuple:

tup = (1,2,3,4,5)

for n in tup:
    print(n, end = " - ")

Les sorties:  

1 - 2 - 3 - 4 - 5 - 

Un autre exemple:

list_of_tuples = [(1,2),('A','B'), (3,4), ('Cat', 'Dog')]
for item in list_of_tuples:
    print(item)

Les sorties:

(1, 2)
('A', 'B')
(3, 4)
('Cat', 'Dog')

Vous pouvez même décompresser votre tuple comme ceci:

list_of_tuples = [(1,2),('A','B'), (3,4), ('Cat', 'Dog')]

# Tuple unpacking so that you can deal with elements inside of the Tuple individually
for (item1, item2) in list_of_tuples:
    print(item1, item2)   

Les sorties:

1 2
A B
3 4
Cat Dog

autre variante:

list_of_tuples = [(1,2),('A','B'), (3,4), ('Cat', 'Dog')]
for (item1, item2) in list_of_tuples:
    print(item1)
    print(item2)
    print('\n')

Les sorties:

1
2


A
B


3
4


Cat
Dog
0
Stryker

La meilleure façon d’y parvenir est d’utiliser le caractère \r

Essayez juste le code ci-dessous:

import time
for n in range(500):
  print(n, end='\r')
  time.sleep(0.01)
print()  # start new line so most recently printed number stays
0
vitiral

Tant de réponses compliquées. Si vous avez python 3, mettez simplement \r au début de l'impression, puis ajoutez end='', flush=True:

import time

for i in range(10):
    print(f'\r{i} foo bar', end='', flush=True)
    time.sleep(0.5)

Ceci écrira 0 foo bar, puis 1 foo bar etc, sur place.

0
Hugh Perkins

Si vous voulez seulement imprimer les chiffres, vous pouvez éviter la boucle.

# python 3
import time

startnumber = 1
endnumber = 100

# solution A without a for loop
start_time = time.clock()
m = map(str, range(startnumber, endnumber + 1))
print(' '.join(m))
end_time = time.clock()
timetaken = (end_time - start_time) * 1000
print('took {0}ms\n'.format(timetaken))

# solution B: with a for loop
start_time = time.clock()
for i in range(startnumber, endnumber + 1):
    print(i, end=' ')
end_time = time.clock()
timetaken = (end_time - start_time) * 1000
print('\ntook {0}ms\n'.format(timetaken))

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 25 27 27 29 30 31 32 33 34 35 36 37 38 39 39 41 42 42 44 44 45 46 47 48 49 50 50 51 52 53 54 55 56 57 59 60 61 62 63 64 65 67 67 69 69 72 72 74 74 76 76 78 78 80 80 82 82 84 83 86 85 86 87 88 89 90 91 92 93 95 95 96 97 98 99 100 a pris 21.1986929975ms

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 25 27 27 29 30 31 32 33 34 35 36 37 38 39 39 41 42 42 44 44 45 46 47 48 49 50 50 51 52 53 54 55 56 57 59 60 61 62 63 64 65 67 67 69 69 72 72 74 74 76 76 78 78 80 80 82 82 84 83 86 85 86 87 88 89 90 91 92 93 95 95 96 97 98 99 100 .__ a pris 491,466823551ms

0
Mahmoud Kassem