Wie schreibe ich die Ausgabe an derselben Stelle auf der Konsole?


158

Ich bin neu in Python und schreibe einige Skripte, um das Herunterladen von Dateien von FTP-Servern usw. zu automatisieren. Ich möchte den Fortschritt des Downloads anzeigen, aber ich möchte, dass er an derselben Position bleibt, wie z.

Ausgabe:

Herunterladen der Datei FooFile.txt [47%]

Ich versuche so etwas zu vermeiden:

     Downloading File FooFile.txt [47%]
     Downloading File FooFile.txt [48%]
     Downloading File FooFile.txt [49%]

Wie soll ich das machen?


Duplizieren : Wie kann ich in einer Befehlszeilenanwendung über die aktuelle Zeile drucken?


1
Vielleicht interessiert Sie dieses benutzerfreundliche Modul, es ist eine Textfortschrittsleiste. pypi.python.org/pypi/progressbar/2.2
wim

Antworten:


254

Sie können auch den Wagenrücklauf verwenden:

sys.stdout.write("Download progress: %d%%   \r" % (progress) )
sys.stdout.flush()

13
Sehr häufige und einfache Lösung. Hinweis: Wenn Ihre Leitung länger als die Breite Ihres Terminals ist, wird dies hässlich.
Ephemient

5
Ich musste auch einen Aufruf an sys.stdout.flush () hinzufügen, damit der Cursor nicht
herumsprang

19
Ist dies mit mehreren Zeilen möglich? Nehmen wir an, ich habe drei verschiedene Downloads und möchte den Fortschritt jedes einzelnen in einer eigenen Zeile anzeigen.
EarlCrapstone

11
Ich setze das gerne \ran den Anfang der Zeile und füge ein hinzu \x1b[K, um den vorherigen Text zu löschen.
August

11
Es scheint, als ob die einfachste Lösung für Python 3 (wie in den Antworten unten erwähnt) ist: print("sample text", end='\r", flush=True)
Cyrus

35

Python 2

Ich mag folgendes:

print 'Downloading File FooFile.txt [%d%%]\r'%i,

Demo:

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="")

Demo:

import time

for i in range(100):
    time.sleep(0.1)
    print('Downloading File FooFile.txt [%d%%]\r'%i, end="")

PyCharm Debugger Console mit 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.')

9
Verwenden Sie dies für Python 3+: print ('Herunterladen der Datei FooFile.txt [% d %%] \ r'% i, end = "")
hkoosha

Auf der PyCharm Debugger-Konsole muss \ r vor dem Text stehen. Andernfalls wird der Text möglicherweise überhaupt nicht oder inkonsistent angezeigt. Ich habe die Version hinzugefügt, die für mich als Bearbeitung funktioniert, da ich in dieser Antwort keinen mehrzeiligen Code schreiben konnte. Ich habe es auf meinen Kern gesetzt, damit die Leute es sehen können, während die Bearbeitung auf die Genehmigung wartet: gist.github.com/yulkang/40168c7729a7a7b96d0116d8b1bc26df
Yul Kang

"\ r" am Ende der Zeichenfolge funktioniert für mich in der Debugger-Konsole von PyCharm 2020.1 (PyCharm 2020.1.2 (Community Edition); Build # PC-201.7846.77, erstellt am 31. Mai 2020).
Battey


15

Drucken Sie das Rücktastezeichen \bmehrmals aus und überschreiben Sie dann die alte Nummer mit der neuen Nummer.


Interessant, ich hatte nicht daran gedacht, es so zu machen.
Chris Ballance

Ich mag das, weil es vorherige Befehle nicht löscht (wenn Sie mehrere Stufen haben, die Sie auf dem Bildschirm lassen möchten)
Nathan Donnellan

3
Die Verwendung des Wagenrücklaufs (z. B. print 'Downloading.... \r') löscht auch keine vorherigen Daten, verhindert jedoch, dass Sie wissen müssen, wie weit die Sicherung zurückliegt.
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="")

Warum ist das besser als oben (ich bin ein Python n00b, bitte entschuldigen Sie meine Unwissenheit :-))?
BalinKingOfMoria CMs

7

Für Python 3xx:

import time
for i in range(10):
    time.sleep(0.2) 
    print ("\r Loading... {}".format(i)+str(i), end="")

4

Eine nette Lösung, die für mich funktioniert hat, ist:

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("")

Das sys.stdout.flushist wichtig, sonst wird es sehr klobig und der print("")On-for-Loop-Ausgang ist ebenfalls wichtig.

UPDATE : Wie in den Kommentaren erwähnt, printhat auch ein flushArgument. Also wird auch folgendes funktionieren:

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("")

1
In modernem Python können Sie ein Argument von flush=Trueto angeben print, sodass kein zusätzlicher sys.stdout.flush()Aufruf erforderlich ist .
PM 2Ring

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="")
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.