web-dev-qa-db-fra.com

Imprimer sur la même ligne et non sur une nouvelle ligne en python

En gros, je veux faire le contraire de ce que ce gars a fait… hehe.

Script Python: Affiche chaque fois la nouvelle ligne dans Shell plutôt que de mettre à jour la ligne existante

J'ai un programme qui me dit jusqu'où il se trouve.

for i in some_list:
    #do a bunch of stuff.
    print i/len(some_list)*100," percent complete"

Donc si len (some_list) avait 50 ans, je ferais imprimer cette dernière ligne 50 fois. Je veux imprimer une ligne et continuer à mettre à jour cette ligne. Je sais que je sais que c’est probablement la question la plus délicate que vous lisiez toute la journée. Je n'arrive pas à comprendre les quatre mots que je dois mettre dans Google pour obtenir la réponse.

Mettre à jour! J'ai essayé la suggestion de MVS qui semblait juste. Le nouveau code

print percent_complete,"           \r",

Pourcentage achevé est juste une chaîne (j'ai résumé la première fois maintenant que j'essaye d'être littéral). Le résultat est maintenant qu'il exécute le programme, n'imprime rien après la fin du programme, puis imprime "terminé à 100%" sur une et une seule ligne.

Sans le retour chariot (mais avec la virgule, la moitié de la suggestion de mvds), rien n’est imprimé jusqu’à la fin. Et puis imprime:

0 percent complete     2 percent complete     3 percent complete     4 percent complete    

Etc. Alors maintenant, le nouveau problème est que, avec la virgule, elle ne s'imprime pas tant que le programme n'est pas terminé.

Avec le retour chariot et sans virgule, il se comporte exactement comme avec aucun des deux.

55
chriscauley

C'est ce qu'on appelle le retour chariot, ou \r

Utilisation

print i/len(some_list)*100," percent complete         \r",

La virgule empêche l'impression d'ajouter une nouvelle ligne. (et les espaces garderont la ligne libre de la sortie précédente)

Aussi, n'oubliez pas de terminer avec un print "" pour obtenir au moins une nouvelle ligne de finalisation!

72
mvds

Depuis python 3.x, vous pouvez faire:

print('bla bla', end='')

(qui peut également être utilisé dans Python 2.6 ou 2.7 en mettant from __future__ import print_function en haut de votre script/module)

Exemple de barre de progression de la console Python:

import time

# status generator
def range_with_status(total):
    """ iterate from 0 to total and show progress in console """
    n=0
    while n<total:
        done = '#'*(n+1)
        todo = '-'*(total-n-1)
        s = '<{0}>'.format(done+todo)
        if not todo:
            s+='\n'        
        if n>0:
            s = '\r'+s
        print(s, end='')
        yield n
        n+=1

# example for use of status generator
for i in range_with_status(10):
    time.sleep(0.1)
26
Remi

Pour moi, ce qui a fonctionné a été une combinaison de réponses de Remi et de siriusd:

from __future__ import print_function
import sys

print(str, end='\r')
sys.stdout.flush()
14
dlchambers

pour la console, vous aurez probablement besoin 

sys.stdout.flush()

forcer la mise à jour. Je pense que l'utilisation de , dans print empêchera stdout de rincer et qu'elle ne sera pas mise à jour 

10
siriusd

Personne n'a mentionné qu'en Python 3 (.quelque chose?) Vous n'avez pas besoin de sys.stdout.flush(). print('foobar', end='', flush=True) fonctionne.

2
LeopardShark

Cela fonctionne pour moi, piraté une fois pour voir si c'est possible, mais jamais réellement utilisé dans mon programme (l'interface graphique est tellement plus agréable):

import time
f = '%4i %%'
len_to_clear = len(f)+1
clear = '\x08'* len_to_clear
print 'Progress in percent:'+' '*(len_to_clear),
for i in range(123):
    print clear+f % (i*100//123),
    time.sleep(0.4)
raw_input('\nDone')
2
Tony Veijalainen
import time
import sys


def update_pct(w_str):
    w_str = str(w_str)
    sys.stdout.write("\b" * len(w_str))
    sys.stdout.write(" " * len(w_str))
    sys.stdout.write("\b" * len(w_str))
    sys.stdout.write(w_str)
    sys.stdout.flush()

for pct in range(0, 101):
    update_pct("{n}%".format(n=str(pct)))
    time.sleep(0.1)

\b va déplacer la position du curseur en arrière d'un espace
Donc nous le déplaçons au début de la ligne
Nous écrivons ensuite des espaces pour effacer la ligne en cours - le curseur se déplace d’un cran
Nous devons donc déplacer le curseur au début de la ligne avant d'écrire nos nouvelles données 

Testé sur Windows cmd en utilisant Python 2.7

2
Robert

Essayez comme ça:

for i in some_list:
    #do a bunch of stuff.
    print i/len(some_list)*100," percent complete",

(Avec une virgule à la fin.)

1
chryss

Basé sur Remi answer for Python 2.7+, utilisez ceci:

from __future__ import print_function
import time

# status generator
def range_with_status(total):
    """ iterate from 0 to total and show progress in console """
    import sys
    n = 0
    while n < total:
        done = '#' * (n + 1)
        todo = '-' * (total - n - 1)
        s = '<{0}>'.format(done + todo)
        if not todo:
            s += '\n'
        if n > 0:
            s = '\r' + s
        print(s, end='\r')
        sys.stdout.flush()
        yield n
        n += 1


# example for use of status generator
for i in range_with_status(50):
    time.sleep(0.2)
0

Pour Python 3.6+ et pour toute list au lieu de ints, ainsi que pour utiliser toute la largeur de votre fenêtre de console et ne pas passer à une nouvelle ligne, vous pouvez utiliser les éléments suivants:

remarque: veuillez noter que la fonction get_console_with() fonctionnera uniquement sur les systèmes Linux. Vous devez donc la réécrire pour qu'elle fonctionne sous Windows.

import os
import time

def get_console_width():
    """Returns the width of console.

    NOTE: The below implementation works only on Linux-based operating systems.
    If you wish to use it on another OS, please make sure to modify it appropriately.
    """
    return int(os.popen('stty size', 'r').read().split()[1])


def range_with_progress(list_of_elements):
    """Iterate through list with a progress bar shown in console."""

    # Get the total number of elements of the given list.
    total = len(list_of_elements)
    # Get the width of currently used console. Subtract 2 from the value for the
    # Edge characters "[" and "]"
    max_width = get_console_width() - 2
    # Start iterating over the list.
    for index, element in enumerate(list_of_elements):
        # Compute how many characters should be printed as "done". It is simply
        # a percentage of work done multiplied by the width of the console. That
        # is: if we're on element 50 out of 100, that means we're 50% done, or
        # 0.5, and we should mark half of the entire console as "done".
        done = int(index / total * max_width)
        # Whatever is left, should be printed as "unfinished"
        remaining = max_width - done
        # Print to the console.
        print(f'[{done * "#"}{remaining * "."}]', end='\r')
        # yield the element to work with it
        yield element
    # Finally, print the full line. If you wish, you can also print whitespace
    # so that the progress bar disappears once you are done. In that case do not
    # forget to add the "end" parameter to print function.
    print(f'[{max_width * "#"}]')


if __== '__main__':
    list_of_elements = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
    for e in range_with_progress(list_of_elements):
        time.sleep(0.2)

0
tamaroth