web-dev-qa-db-fra.com

sortie sur la même ligne écrasant la sortie précédente? python (2.5)

J'écris un téléchargeur FTP simple. Une partie du code ressemble à ceci:

ftp.retrbinary("RETR " + file_name, process)

j'appelle un processus de fonction pour gérer le rappel:

def process(data):
    print os.path.getsize(file_name)/1024, 'KB / ', size, 'KB downloaded!'
    file.write(data)

et la sortie est quelque chose comme ceci:

1784  KB / KB 1829 downloaded!
1788  KB / KB 1829 downloaded!
etc...   

mais Je veux qu'il imprime cette ligne et la réimprime/la rafraîchisse la prochaine fois pour qu'il ne le montre qu'une seule fois et que je verrai les progrès de ce téléchargement ...

Comment ceci peut être fait?

83
Kristian

Voici le code pour Python 3.x:

print(os.path.getsize(file_name)/1024+'KB / '+size+' KB downloaded!', end='\r')

Le mot-clé end= Correspond au travail effectué ici. Par défaut, print() se termine par un caractère de nouvelle ligne (\n), Mais il peut être remplacé par une chaîne différente. Dans ce cas, la fin de la ligne avec un retour à la ligne renvoie le curseur au début de la ligne en cours. Il n’est donc pas nécessaire d’importer le module sys pour ce type d’utilisation simple. print() a réellement n certain nombre d'arguments de mots clés qui peuvent être utilisés pour simplifier grandement le code.

Pour utiliser le même code sur Python 2.6+, placez la ligne suivante en haut du fichier:

from __future__ import print_function
147
Kudzu

Si vous souhaitez simplement modifier une seule ligne, utilisez \r. \r signifie le retour chariot. Son effet est uniquement de remettre le curseur au début de la ligne en cours. Cela n'efface rien. De même, \b peut être utilisé pour reculer d’un caractère. (certains terminaux peuvent ne pas supporter toutes ces fonctionnalités)

import sys

def process(data):
    size_str = os.path.getsize(file_name)/1024, 'KB / ', size, 'KB downloaded!'
    sys.stdout.write('%s\r' % size_str)
    sys.stdout.flush()
    file.write(data)
36
Sam Dolan

Regardez le documentation du module curses et le module curses HOWTO .

Exemple vraiment basique:

import time
import curses

stdscr = curses.initscr()

stdscr.addstr(0, 0, "Hello")
stdscr.refresh()

time.sleep(1)

stdscr.addstr(0, 0, "World! (with curses)")
stdscr.refresh()
17
Andrea Spadaccini

Voici ma petite classe qui peut réimprimer des blocs de texte. Il efface correctement le texte précédent afin que vous puissiez écraser votre ancien texte avec un nouveau texte plus court sans créer de désordre.

import re, sys

class Reprinter:
    def __init__(self):
        self.text = ''

    def moveup(self, lines):
        for _ in range(lines):
            sys.stdout.write("\x1b[A")

    def reprint(self, text):
        # Clear previous text by overwritig non-spaces with spaces
        self.moveup(self.text.count("\n"))
        sys.stdout.write(re.sub(r"[^\s]", " ", self.text))

        # Print new text
        lines = min(self.text.count("\n"), text.count("\n"))
        self.moveup(lines)
        sys.stdout.write(text)
        self.text = text

reprinter = Reprinter()

reprinter.reprint("Foobar\nBazbar")
reprinter.reprint("Foo\nbar")
9
Bouke Versteegh

J'ai trouvé que pour une simple instruction print dans python 2.7, il suffit de mettre une virgule à la fin après votre '\r'.

print os.path.getsize(file_name)/1024, 'KB / ', size, 'KB downloaded!\r',

C’est plus court que d’autres solutions non python 3, mais aussi plus difficile à maintenir.

7
Matt Ellen

Vous pouvez simplement ajouter '\ r' à la fin de la chaîne plus une virgule à la fin de la fonction print. Par exemple:

print(os.path.getsize(file_name)/1024+'KB / '+size+' KB downloaded!\r'),
4
Moustafa Saleh

J'utilise spyder 3.3.1 - windows 7 - python 3.6 bien que le flush ne soit peut-être pas nécessaire. Sur la base de cette publication - https://github.com/spyder-ide/ spyder/issues/3437

   #works in spyder ipython console - \r at start of string , end=""
import time
import sys
    for i in range(20):
        time.sleep(0.5)
        print(f"\rnumber{i}",end="")
        sys.stdout.flush()
2
JoePythonKing

pour écraser la ligne précédente dans python tout ce dont vous avez besoin est d'ajouter fin = '\ r' à la fonction d'impression, testez cet exemple:

import time
for j in range(1,5):
   print('waiting : '+j, end='\r')
   time.sleep(1)
0
Amirouche Zeggagh