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.

4voto

Brian Khuu Punkte 1117

Auf der Grundlage der obigen Antworten und anderer ähnlicher Fragen zum CLI-Fortschrittsbalken habe ich, glaube ich, eine allgemeine gemeinsame Antwort auf alle Fragen gefunden. Prüfen Sie es unter https://stackoverflow.com/a/15860757/2254146

Zusammengefasst lautet der Code wie folgt:

import time, sys

# update_progress() : Displays or updates a console progress bar
## Accepts a float between 0 and 1. Any int will be converted to a float.
## A value under 0 represents a 'halt'.
## A value at 1 or bigger represents 100%
def update_progress(progress):
    barLength = 10 # Modify this to change the length of the progress bar
    status = ""
    if isinstance(progress, int):
        progress = float(progress)
    if not isinstance(progress, float):
        progress = 0
        status = "error: progress var must be float\r\n"
    if progress < 0:
        progress = 0
        status = "Halt...\r\n"
    if progress >= 1:
        progress = 1
        status = "Done...\r\n"
    block = int(round(barLength*progress))
    text = "\rPercent: [{0}] {1}% {2}".format( "#"*block + "-"*(barLength-block), progress*100, status)
    sys.stdout.write(text)
    sys.stdout.flush()

Sieht aus wie

Prozentsatz: [##########] 99,0%

4voto

Ib33X Punkte 5954

Ich verwende Fortschritt von reddit . Ich mag es, weil es den Fortschritt für jedes Element in einer Zeile ausdrucken kann, und es sollte die Ausdrucke nicht aus dem Programm löschen.

Bearbeiten: Link korrigiert

2 Stimmen

Ihr Link ist fehlerhaft - die tatsächliche Zeile im Quellcode ist die 1274ste, nicht die 1124ste! Also, der richtige Link ist dieser: github.com/reddit/reddit/blob/master/r2/r2/lib/utils/

0 Stimmen

Diese Variante hat für meinen Geschmack das beste Design: sie verwendet Iteratoren und arbeitet möglichst mit jeder Art von messbarer Arbeit, sie zeigt die verstrichene Zeit an.

4voto

Andy Mikhaylenko Punkte 1299

3voto

Malcolm Box Punkte 3879

Ich empfehle die Verwendung von tqdm - https://pypi.python.org/pypi/tqdm - die es einfach macht, eine beliebige Iterable oder einen Prozess in einen Fortschrittsbalken zu verwandeln, und die alle notwendigen Eingriffe in die Terminals übernimmt.

Aus der Dokumentation: "tqdm kann leicht Callbacks/Hooks und manuelle Updates unterstützen. Hier ist ein Beispiel mit urllib"

import urllib
from tqdm import tqdm

def my_hook(t):
  """
  Wraps tqdm instance. Don't forget to close() or __exit__()
  the tqdm instance once you're done with it (easiest using `with` syntax).

  Example
  -------

  >>> with tqdm(...) as t:
  ...     reporthook = my_hook(t)
  ...     urllib.urlretrieve(..., reporthook=reporthook)

  """
  last_b = [0]

  def inner(b=1, bsize=1, tsize=None):
    """
    b  : int, optional
        Number of blocks just transferred [default: 1].
    bsize  : int, optional
        Size of each block (in tqdm units) [default: 1].
    tsize  : int, optional
        Total size (in tqdm units). If [default: None] remains unchanged.
    """
    if tsize is not None:
        t.total = tsize
    t.update((b - last_b[0]) * bsize)
    last_b[0] = b
  return inner

eg_link = 'http://www.doc.ic.ac.uk/~cod11/matryoshka.zip'
with tqdm(unit='B', unit_scale=True, miniters=1,
          desc=eg_link.split('/')[-1]) as t:  # all optional kwargs
    urllib.urlretrieve(eg_link, filename='/dev/null',
                       reporthook=my_hook(t), data=None)

2voto

Storm-Eyes Punkte 761

Mit den tollen Ratschlägen oben habe ich den Fortschrittsbalken ausgearbeitet.

Ich möchte jedoch auf einige Unzulänglichkeiten hinweisen

  1. Jedes Mal, wenn der Fortschrittsbalken geleert wird, beginnt er in einer neuen Zeile

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

    wie diese:
    [] 0%
    [#]10%
    [##]20%
    [###]30%

Die eckige Klammer ']' und die Prozentzahl auf der rechten Seite verschieben sich nach rechts, wenn das '###' länger wird.
3. Ein Fehler tritt auf, wenn der Ausdruck "progress / 10" keine ganze Zahl zurückgeben kann.

Und der folgende Code behebt das obige Problem.

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

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