574 Stimmen

Textfortschrittsbalken im Terminal mit Blockzeichen

Ich habe eine einfache Konsolenanwendung zum Hoch- und Herunterladen von Dateien von einem FTP-Server unter Verwendung der ftplib geschrieben.

Ich möchte, dass die App eine Visualisierung des Download/Upload-Fortschritts für den Benutzer anzeigt; jedes Mal, wenn ein Datenpaket heruntergeladen wird, möchte ich, dass sie eine Fortschrittsaktualisierung bereitstellt, auch wenn es nur eine numerische Darstellung wie ein Prozentsatz ist.

Wichtig ist, dass ich vermeiden möchte, den gesamten Text zu löschen, der in den vorherigen Zeilen auf der Konsole ausgegeben wurde (d. h. ich möchte nicht das gesamte Terminal "löschen", während ich den aktualisierten Fortschritt ausdrucke).

Dies scheint eine ziemlich häufige Aufgabe - wie kann ich über die Erstellung eines Fortschrittsbalken oder ähnliche Visualisierung, die Ausgaben zu meiner Konsole unter Beibehaltung der vorherigen Programmausgabe gehen?

0 Stimmen

Sieht aus wie ein Duplikat dieser gestern gestellten Frage: stackoverflow.com/questions/3160699/python-progress-bar/3162864 Sie sollten also Fisch verwenden pypi.python.org/pypi/fish

37 Stimmen

"Verwenden Sie einfach eine grafische Benutzeroberfläche" verkennt, dass grafische Benutzeroberflächen in einigen Situationen (schnelle Lernkurve, Ad-hoc-Sondierungs- oder interaktive oder einmalige Aktivitäten) großartig sind, während Befehlszeilentools für andere Situationen großartig sind (erfahrene Benutzer, die Ad-hoc-Anwendungen im Handumdrehen zusammenstellen, um eine sorgfältig definierte Operation viele Male durchzuführen).

31 Stimmen

Ich habe für die Wiedereröffnung gestimmt. Die Frage scheint mir nicht zu weit gefasst zu sein.

756voto

Greenstick Punkte 7799

Python 3

Ein einfacher, anpassbarer Fortschrittsbalken

Hier finden Sie eine Zusammenfassung vieler der unten aufgeführten Antworten, die ich regelmäßig verwende (keine Importe erforderlich).

Anmerkung: Der gesamte Code in dieser Antwort wurde für Python 3 erstellt; siehe Ende der Antwort, um diesen Code mit Python 2 zu verwenden.

# Print iterations progress
def printProgressBar (iteration, total, prefix = '', suffix = '', decimals = 1, length = 100, fill = '', printEnd = "\r"):
    """
    Call in a loop to create terminal progress bar
    @params:
        iteration   - Required  : current iteration (Int)
        total       - Required  : total iterations (Int)
        prefix      - Optional  : prefix string (Str)
        suffix      - Optional  : suffix string (Str)
        decimals    - Optional  : positive number of decimals in percent complete (Int)
        length      - Optional  : character length of bar (Int)
        fill        - Optional  : bar fill character (Str)
        printEnd    - Optional  : end character (e.g. "\r", "\r\n") (Str)
    """
    percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
    filledLength = int(length * iteration // total)
    bar = fill * filledLength + '-' * (length - filledLength)
    print(f'\r{prefix} |{bar}| {percent}% {suffix}', end = printEnd)
    # Print New Line on Complete
    if iteration == total: 
        print()

Verwendungsbeispiele

import time

# A List of Items
items = list(range(0, 57))
l = len(items)

# Initial call to print 0% progress
printProgressBar(0, l, prefix = 'Progress:', suffix = 'Complete', length = 50)
for i, item in enumerate(items):
    # Do stuff...
    time.sleep(0.1)
    # Update Progress Bar
    printProgressBar(i + 1, l, prefix = 'Progress:', suffix = 'Complete', length = 50)

Beispielhafte Ausgabe

Progress: |-----| 90.0% Complete

Update

In den Kommentaren wurde über eine Option diskutiert, die es ermöglicht, den Fortschrittsbalken dynamisch an die Breite des Terminalfensters anzupassen. Ich empfehle dies zwar nicht, aber hier ist eine . die diese Funktion implementiert (und auf die Vorbehalte hinweist).

Einzelaufruf-Version des oben genannten

In einem Kommentar wurde auf eine schöne Antwort als Antwort auf eine ähnliche Frage gepostet. Mir gefiel die Benutzerfreundlichkeit, die darin demonstriert wurde, und ich schrieb eine ähnliche Antwort, verzichtete aber auf den Import der sys Modul, wobei einige der Funktionen des ursprünglichen printProgressBar Funktion oben.

Zu den Vorteilen dieses Ansatzes gegenüber der obigen Originalfunktion gehören der Wegfall des ersten Funktionsaufrufs, um den Fortschrittsbalken bei 0 % zu drucken, und die Verwendung von enumerate wird optional (d.h. sie ist nicht mehr ausdrücklich erforderlich, damit die Funktion funktioniert).

def progressBar(iterable, prefix = '', suffix = '', decimals = 1, length = 100, fill = '', printEnd = "\r"):
    """
    Call in a loop to create terminal progress bar
    @params:
        iterable    - Required  : iterable object (Iterable)
        prefix      - Optional  : prefix string (Str)
        suffix      - Optional  : suffix string (Str)
        decimals    - Optional  : positive number of decimals in percent complete (Int)
        length      - Optional  : character length of bar (Int)
        fill        - Optional  : bar fill character (Str)
        printEnd    - Optional  : end character (e.g. "\r", "\r\n") (Str)
    """
    total = len(iterable)
    # Progress Bar Printing Function
    def printProgressBar (iteration):
        percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
        filledLength = int(length * iteration // total)
        bar = fill * filledLength + '-' * (length - filledLength)
        print(f'\r{prefix} |{bar}| {percent}% {suffix}', end = printEnd)
    # Initial Call
    printProgressBar(0)
    # Update Progress Bar
    for i, item in enumerate(iterable):
        yield item
        printProgressBar(i + 1)
    # Print New Line on Complete
    print()

Verwendungsbeispiele

import time

# A List of Items
items = list(range(0, 57))

# A Nicer, Single-Call Usage
for item in progressBar(items, prefix = 'Progress:', suffix = 'Complete', length = 50):
    # Do stuff...
    time.sleep(0.1)

Beispielhafte Ausgabe

Progress: |-----| 90.0% Complete

Python 2

Um die oben genannten Funktionen in Python 2 zu verwenden, setzen Sie die Kodierung am Anfang Ihres Skripts auf UTF-8:

# -*- coding: utf-8 -*-

Und ersetzen Sie die Python 3 String-Formatierung in dieser Zeile:

print(f'\r{prefix} |{bar}| {percent}% {suffix}', end = printEnd)

Mit Python 2 String-Formatierung:

print('\r%s |%s| %s%% %s' % (prefix, bar, percent, suffix), end = printEnd)

25 Stimmen

Dieses Snippet funktioniert hervorragend! Ich habe ein paar kleinere Probleme zu begegnen, so dass ich einige kleinere Änderungen (PEP-8, Standard-Kodierung für Nicht-Ascii-Zeichen) und warf sie in einem Gist hier: gist.github.com/aubricus/f91fb55dc6ba5557fbab06119420dd6a

3 Stimmen

Erwähnenswert ist, dass die UTF-8-Deklaration nicht notwendig ist, es sei denn, Sie verwenden Python 2 @Aubricus

0 Stimmen

SyntaxFehler: Nicht-ASCII-Zeichen ' \xe2 ' in Zeile 5, aber keine Kodierung angegeben

341voto

Stephen Punkte 45678

Schreiben ' \r ' setzt den Cursor zurück an den Anfang der Zeile.

Hier wird ein Prozentzähler angezeigt:

import time
import sys

for i in range(100):
    time.sleep(1)
    sys.stdout.write("\r%d%%" % i)
    sys.stdout.flush()

3 Stimmen

Eingefügt und ausgeführt. Es wird jedes Mal in eine neue Zeile gedruckt. Ich möchte, dass die Zahl in der gleichen Zeile aktualisiert wird :)

0 Stimmen

@bobber205 : Ich habe es gerade auf zwei verschiedenen Betriebssystemen (mac & linux) und zwei verschiedenen Python-Versionen ausprobiert. Es wird in einer Zeile gedruckt :) Sind Sie sicher, dass Sie ',' am Ende der Zeile print Aussage?

0 Stimmen

Ich verwende Python 2.6. Ich habe es in Aptana Studio und auf der Kommandozeile versucht. Druckt auf mehreren Zeilen :(

249voto

jfs Punkte 370717

tqdm: Fügen Sie in einer Sekunde eine Fortschrittsanzeige zu Ihren Schleifen hinzu :

>>> import time
>>> from tqdm import tqdm
>>> for i in tqdm(range(100)):
...     time.sleep(1)
... 
|###-------| 35/100  35% [elapsed: 00:35 left: 01:05,  1.00 iters/sec]

tqdm repl session

0 Stimmen

Welche Python-Shell verwenden Sie?

2 Stimmen

@xotonic der Link sagt, dass es so ist ptpython

1 Stimmen

Sicher, ziehen Sie eine Lib für 20 Zeilen Funktion :D

129voto

aviraldg Punkte 9311

Schreiben Sie eine \r an die Konsole. Das ist eine "Wagenrücklauf" was dazu führt, dass der gesamte nachfolgende Text am Anfang der Zeile wiedergegeben wird. Etwa so:

def update_progress(progress):
    print '\r[{0}] {1}%'.format('#'*(progress/10), progress)

was Ihnen etwas wie: [ ########## ] 100%

0 Stimmen

Tun ' \r ' + myPercentage Ausdruck?

22 Stimmen

Do \r und schreiben Sie dann die ganze Zeile noch einmal aus. Im Grunde genommen: print("\rProgress: [{0:50s}] {1:.1f}%".format('#' * int(amtDone * 50), amtDone * 100)) , donde amtDone ist eine Fließkommazahl zwischen 0 und 1.

0 Stimmen

@MikeDeSimone, das sieht nach der besten Bar aus, wenn man nicht gerade Curses verwendet.

85voto

Vladimir Ignatyev Punkte 1904

Sie besteht aus weniger als 10 Zeilen Code.

Das Wesentliche hier: https://gist.github.com/vladignatyev/06860ec2040cb497f0f3

import sys

def progress(count, total, suffix=''):
    bar_len = 60
    filled_len = int(round(bar_len * count / float(total)))

    percents = round(100.0 * count / float(total), 1)
    bar = '=' * filled_len + '-' * (bar_len - filled_len)

    sys.stdout.write('[%s] %s%s ...%s\r' % (bar, percents, '%', suffix))
    sys.stdout.flush()  # As suggested by Rom Ruben

enter image description here

3 Stimmen

Fügt "sys.stdout.flush()" an das Ende der Funktion an.

0 Stimmen

Bei mir kommt es in eine neue Zeile

0 Stimmen

@GM welches Betriebssystem/welche Plattform verwenden Sie?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X