Frage

Gibt es eine gute Möglichkeit, die folgenden zu tun?

ich eine einfache Konsolenanwendung geschrieben Upload und Download von Dateien von einem FTP-Server der ftplib verwenden.

Jedes Mal, einige Datenblöcke heruntergeladen werden, möchte ich einen Text Fortschrittsbalken aktualisieren, selbst wenn es nur eine Zahl.

Aber ich will nicht alle den Text löschen, die auf die Konsole ausgegeben worden sind. (Doing a "clear" und dann Drucken des aktualisierten Prozentsatz.)

War es hilfreich?

Lösung

Eine einfache, individuell gestaltete Progress Bar

Hier ist ein Aggregat von vielen der Antworten unten, dass ich regelmäßig nutzen (keine Importe erforderlich).

# Print iterations progress
def printProgressBar (iteration, total, prefix = '', suffix = '', decimals = 1, length = 100, fill = '█'):
    """
    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)
    """
    percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
    filledLength = int(length * iteration // total)
    bar = fill * filledLength + '-' * (length - filledLength)
    print('\r%s |%s| %s%% %s' % (prefix, bar, percent, suffix), end = '\r')
    # Print New Line on Complete
    if iteration == total: 
        print()

Hinweis: Das ist für Python 3 ist; siehe die Kommentare Informationen zur Verwendung dieser in Python 2.

Proben Verbrauch

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)

Beispielausgabe:

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

Update

Es gab Diskussion in den Kommentaren in Bezug auf eine Option, die die Statusleiste ermöglicht die Terminal Fensterbreite dynamisch anzupassen. Während ich das nicht empfehlen, hier ist ein Kern , dass diese Funktion implementiert (und Notizen der Einsprüche) .

Andere Tipps

Schreiben ‚\ r‘ wird der Cursor an den Anfang der Zeile.

Es erscheint ein Prozentsatz Zähler:

import time
import sys

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

tqdm: fügen Sie einen Fortschrittsanzeige auf Ihre Loops in einem zweiten :

>>> 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 Sitzung

eine \r an die Konsole schreiben. Das ist ein „Carriage Return“ , die die gesamten Text verursacht, nachdem es zu Beginn des Echo wird Linie. So etwas wie:

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

, die Sie so etwas wie: [ ########## ] 100%

Es ist weniger als 10 Zeilen Code.

Der Kern 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

eingeben Bild Beschreibung hier

Versuchen Sie die Bibliothek durch die Mozart von Python geschrieben klicken, Armin Ronacher.

$ pip install click # both 2 and 3 compatible

ein einfachen Fortschrittsbalken erstellen:

import click

with click.progressbar(range(1000000)) as bar:
    for i in bar:
        pass 

Dies ist, wie es aussieht:

# [###-------------------------------]    9%  00:01:14

Anpassen, um Ihre Herzen Inhalt:

import click, sys

with click.progressbar(range(100000), file=sys.stderr, show_pos=True, width=70, bar_template='(_(_)=%(bar)sD(_(_| %(info)s', fill_char='=', empty_char=' ') as bar:
    for i in bar:
        pass

Benutzerdefinierte aussehen:

(_(_)===================================D(_(_| 100000/100000 00:00:02

Es gibt noch weitere Optionen finden Sie in der API-Dokumentation :

 click.progressbar(iterable=None, length=None, label=None, show_eta=True, show_percent=None, show_pos=False, item_show_func=None, fill_char='#', empty_char='-', bar_template='%(label)s [%(bar)s] %(info)s', info_sep=' ', width=36, file=None, color=None)

Ich weiß, ich bin zu spät, um das Spiel, aber hier ist ein etwas Yum-Stil (Red Hat), die ich (nicht für 100% Genauigkeit gehen schrieb hier, aber wenn Sie einen Fortschrittsbalken für das Niveau der Genauigkeit verwenden , dann irrst du dich sowieso):

import sys

def cli_progress_test(end_val, bar_length=20):
    for i in xrange(0, end_val):
        percent = float(i) / end_val
        hashes = '#' * int(round(percent * bar_length))
        spaces = ' ' * (bar_length - len(hashes))
        sys.stdout.write("\rPercent: [{0}] {1}%".format(hashes + spaces, int(round(percent * 100))))
        sys.stdout.flush()

Sollte etwas produzieren wie folgt aussehen:

Percent: [##############      ] 69%

... wo die Klammern bleiben stationär und nur die Hashes zu erhöhen.

Dies könnte funktionieren besser als Dekorateur. Für einen weiteren Tag ...

Überprüfen Sie diese Bibliothek: clint

es hat eine Menge von Features, einschließlich einer Statusleiste:

from time import sleep  
from random import random  
from clint.textui import progress  
if __name__ == '__main__':
    for i in progress.bar(range(100)):
        sleep(random() * 0.2)

    for i in progress.dots(range(100)):
        sleep(random() * 0.2)

Link bietet einen schnellen Überblick über seine Funktionen

Hier ist ein schönes Beispiel für eine progressbar in Python geschrieben: http : //nadiana.com/animated-terminal-progress-bar-in-python

Aber wenn Sie es selbst zu schreiben. Sie könnten das curses Modul verwenden, um Dinge einfacher zu machen:)

[Bearbeiten] Vielleicht ist einfacher, nicht das Wort für Flüche. Aber wenn Sie eine ausgewachsene cui als Flüche erstellen möchten kümmert sich um eine Menge Sachen für Sie.

[Bearbeiten] Da die alte Verbindung tot ist, ich habe meine eigene Version eines Python Progressbar setzen, sie bekommen hier: https: //github.com/WoLpH/python-progressbar

import time,sys

for i in range(100+1):
    time.sleep(0.1)
    sys.stdout.write(('='*i)+(''*(100-i))+("\r [ %d"%i+"% ] "))
    sys.stdout.flush()

Ausgang

[29%] ===================

und nur auf den Stapel hinzuzufügen, ist hier ein Objekt können Sie

import sys

class ProgressBar(object):
    DEFAULT_BAR_LENGTH = 65
    DEFAULT_CHAR_ON  = '='
    DEFAULT_CHAR_OFF = ' '

    def __init__(self, end, start=0):
        self.end    = end
        self.start  = start
        self._barLength = self.__class__.DEFAULT_BAR_LENGTH

        self.setLevel(self.start)
        self._plotted = False

    def setLevel(self, level):
        self._level = level
        if level < self.start:  self._level = self.start
        if level > self.end:    self._level = self.end

        self._ratio = float(self._level - self.start) / float(self.end - self.start)
        self._levelChars = int(self._ratio * self._barLength)

    def plotProgress(self):
        sys.stdout.write("\r  %3i%% [%s%s]" %(
            int(self._ratio * 100.0),
            self.__class__.DEFAULT_CHAR_ON  * int(self._levelChars),
            self.__class__.DEFAULT_CHAR_OFF * int(self._barLength - self._levelChars),
        ))
        sys.stdout.flush()
        self._plotted = True

    def setAndPlot(self, level):
        oldChars = self._levelChars
        self.setLevel(level)
        if (not self._plotted) or (oldChars != self._levelChars):
            self.plotProgress()

    def __add__(self, other):
        assert type(other) in [float, int], "can only add a number"
        self.setAndPlot(self._level + other)
        return self
    def __sub__(self, other):
        return self.__add__(-other)
    def __iadd__(self, other):
        return self.__add__(other)
    def __isub__(self, other):
        return self.__add__(-other)

    def __del__(self):
        sys.stdout.write("\n")

if __name__ == "__main__":
    import time
    count = 150
    print "starting things:"

    pb = ProgressBar(count)

    #pb.plotProgress()
    for i in range(0, count):
        pb += 1
        #pb.setAndPlot(i + 1)
        time.sleep(0.01)
    del pb

    print "done"

Ergebnisse in:

starting things:
  100% [=================================================================]
done

Dies würde am häufigsten als „over the top“ in Betracht gezogen werden, aber es ist praktisch, wenn Sie es verwenden viel

Ausführen dieses an der Python-Befehlszeile ( nicht in jedem IDE oder Entwicklungsumgebung):

>>> import threading
>>> for i in range(50+1):
...   threading._sleep(0.5)
...   print "\r%3d" % i, ('='*i)+('-'*(50-i)),

Arbeiten auf meinem Windows-System.

Installieren tqdm. (pip install tqdm) und verwenden Sie es wie folgt:

import time
from tqdm import tqdm
for i in tqdm(range(1000)):
    time.sleep(0.01)

Das ist ein 10 Sekunden Fortschrittsbalken thatll Ausgabe etwas wie folgt aus:

47%|██████████████████▊                     | 470/1000 [00:04<00:05, 98.61it/s]

Ich bin mit Fortschritt von reddit . Ich mag es, weil es Fortschritte für jedes Element in einer Zeile drucken kann, und es soll nicht Ausdrucke aus dem Programm zu löschen.

Edit: feste Querung

auf der Grundlage der oben genannten Antworten und ähnliche Fragen zu CLI Fortschrittsbalken, ich glaube, ich habe eine allgemeine gemeinsame Antwort auf alle von ihnen. Prüfen Sie es unter https://stackoverflow.com/a/15860757/2254146

Insgesamt ist der Code folgendermaßen aus:

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

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

Ich empfehle tqdm mit - https://pypi.python.org/pypi/tqdm -., die es einfach zu machen jeden iterable oder Prozess in einen Fortschrittsbalken macht, und kümmert sich um alle Spielerisch mit Terminals erforderlich

Aus der Dokumentation: „tqdm leicht Rückrufe / Haken und manuelles Updates unterstützen kann hier 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)

Versuchen Sie, dieses Paket zu installieren: pip install progressbar2:

import time
import progressbar

for i in progressbar.progressbar(range(100)):
    time.sleep(0.02)

progresssbar Github: https://github.com/WoLpH/python-progressbar

import sys
def progresssbar():
         for i in range(100):
            time.sleep(1)
            sys.stdout.write("%i\r" % i)

progressbar()

Hinweis: Wenn Sie diese in interaktiven interepter laufen Sie zusätzliche Zahlen ausgedruckt

get

lol Ich schrieb gerade ein ganzes Ding für diesen her der Code Keep in Mind kippen Sie Unicode verwenden, wenn Block ascii täten i verwenden CP437

import os
import time
def load(left_side, right_side, length, time):
    x = 0
    y = ""
    print "\r"
    while x < length:
        space = length - len(y)
        space = " " * space
        z = left + y + space + right
        print "\r", z,
        y += "█"
        time.sleep(time)
        x += 1
    cls()

und Sie nennen es gerne so

print "loading something awesome"
load("|", "|", 10, .01)

, so dass es wie folgt aussieht

loading something awesome
|█████     |

Mit den großen Ratschlägen oben ich die Fortschrittsbalken trainieren.

Allerdings möchte ich einige Mängel hinzuweisen

  1. Jedes Mal, wenn die Fortschrittsbalken gespült werden, wird es auf eine neue Zeile beginnen

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

    wie folgt aus:
    [] 0%
    [#] 10%
    [##] 20%
    [###] 30%

2. Die eckige Klammer ‚]‘ und die Prozentzahl auf der rechten Seite Verschiebung nach rechts als ‚###‘ länger werden.
3. Ein Fehler wird auftreten, wenn der Ausdruck ‚progress / 10‘ kann nicht eine ganze Zahl zurück.

Und der folgende Code wird das Problem beheben oben.

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

Eine sehr einfache Lösung ist es, diesen Code in der Schleife zu setzen:

Setzen Sie diese in dem Körper (das heißt oben) die Datei:

import sys

Setzen Sie dieses in den Körper Ihrer Schleife:

sys.stdout.write("-") # prints a dash for each iteration of loop
sys.stdout.flush() # ensures bar is displayed incrementally

-Code für Python Terminal Fortschrittsbalken

import sys
import time

max_length = 5
at_length = max_length
empty = "-"
used = "%"

bar = empty * max_length

for i in range(0, max_length):
    at_length -= 1

    #setting empty and full spots
    bar = used * i
    bar = bar+empty * at_length

    #\r is carriage return(sets cursor position in terminal to start of line)
    #\0 character escape

    sys.stdout.write("[{}]\0\r".format(bar))
    sys.stdout.flush()

    #do your stuff here instead of time.sleep
    time.sleep(1)

sys.stdout.write("\n")
sys.stdout.flush()

Die Zusammenstellung einige der Ideen, die ich hier gefunden, und das Hinzufügen von geschätzter Restzeit:

import datetime, sys

start = datetime.datetime.now()

def print_progress_bar (iteration, total):

    process_duration_samples = []
    average_samples = 5

    end = datetime.datetime.now()

    process_duration = end - start

    if len(process_duration_samples) == 0:
        process_duration_samples = [process_duration] * average_samples

    process_duration_samples = process_duration_samples[1:average_samples-1] + [process_duration]
    average_process_duration = sum(process_duration_samples, datetime.timedelta()) / len(process_duration_samples)
    remaining_steps = total - iteration
    remaining_time_estimation = remaining_steps * average_process_duration

    bars_string = int(float(iteration) / float(total) * 20.)
    sys.stdout.write(
        "\r[%-20s] %d%% (%s/%s) Estimated time left: %s" % (
            '='*bars_string, float(iteration) / float(total) * 100,
            iteration,
            total,
            remaining_time_estimation
        ) 
    )
    sys.stdout.flush()
    if iteration + 1 == total:
        print 


# Sample usage

for i in range(0,300):
    print_progress_bar(i, 300)

Nun, hier ist der Code, das funktioniert, und ich es vor der Veröffentlichung getestet:

import sys
def prg(prog, fillchar, emptchar):
    fillt = 0
    emptt = 20
    if prog < 100 and prog > 0:
        prog2 = prog/5
        fillt = fillt + prog2
        emptt = emptt - prog2
        sys.stdout.write("\r[" + str(fillchar)*fillt + str(emptchar)*emptt + "]" + str(prog) + "%")
        sys.stdout.flush()
    elif prog >= 100:
        prog = 100
        prog2 = prog/5
        fillt = fillt + prog2
        emptt = emptt - prog2
        sys.stdout.write("\r[" + str(fillchar)*fillt + str(emptchar)*emptt + "]" + str(prog) + "%" + "\nDone!")
        sys.stdout.flush()
    elif prog < 0:
        prog = 0
        prog2 = prog/5
        fillt = fillt + prog2
        emptt = emptt - prog2
        sys.stdout.write("\r[" + str(fillchar)*fillt + str(emptchar)*emptt + "]" + str(prog) + "%" + "\nHalted!")
        sys.stdout.flush()

Vorteile:

  • 20 Zeichenleiste (1 Zeichen für alle 5 (Anzahl weise))
  • Benutzerdefinierte Füllzeichen
  • Benutzerdefinierte leeren Zeichen
  • Halt (eine beliebige Zahl unter 0)
  • Fertig (100 und eine beliebige Anzahl von über 100)
  • Fortschritt Zahl (0-100 (unten und oben für spezielle Funktionen verwendet))
  • Prozentsatz Zahl neben Bar, und es ist eine einzige Zeile

Nachteile:

  • Unterstützt nur ganze Zahlen (es kann geändert werden sie allerdings zu unterstützen, indem die Division einer Integer-Division, also nur prog2 = prog/5 zu prog2 = int(prog/5) ändern)

Hier ist meine Python 3 Lösung:

import time
for i in range(100):
    time.sleep(1)
    s = "{}% Complete".format(i)
    print(s,end=len(s) * '\b')

‚\ b‘ ist ein Schrägstrich, für jedes Zeichen in der Zeichenfolge. Das funktioniert nicht im Windows-cmd-Fenster.

Funktion von Grünholz für 2.7:

def printProgressBar (iteration, total, prefix = '', suffix = '',decimals = 1, length = 100, fill = '#'):

percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
filledLength = int(length * iteration // total)
bar = fill * filledLength + '-' * (length - filledLength)
print'\r%s |%s| %s%% %s' % (prefix, bar, percent, suffix),
sys.stdout.flush()
# Print New Line on Complete                                                                                                                                                                                                              
if iteration == total:
    print()

Der Python-Modul progressbar ist eine gute Wahl. Hier ist mein typischer Code:

import time
import progressbar

widgets = [
    ' ', progressbar.Percentage(),
    ' ', progressbar.SimpleProgress(format='(%(value_s)s of %(max_value_s)s)'),
    ' ', progressbar.Bar('>', fill='.'),
    ' ', progressbar.ETA(format_finished='- %(seconds)s  -', format='ETA: %(seconds)s', ),
    ' - ', progressbar.DynamicMessage('loss'),
    ' - ', progressbar.DynamicMessage('error'),
    '                          '
]

bar = progressbar.ProgressBar(redirect_stdout=True, widgets=widgets)
bar.start(100)
for i in range(100):
    time.sleep(0.1)
    bar.update(i + 1, loss=i / 100., error=i)
bar.finish()

https://pypi.python.org/pypi/progressbar2/3.30.2

Progressbar2 ist eine gute Bibliothek für ascii Basis progressbar für die Kommandozeile Importzeit Import progressbar

bar = progressbar.ProgressBar()
for i in bar(range(100)):
    time.sleep(0.02)
bar.finish()

https://pypi.python.org/pypi/tqdm

tqdm ist eine Alternative von progressbar2 und ich denke, es ist in PIP3 verwenden, aber ich bin nicht sicher, dass

from tqdm import tqdm
for i in tqdm(range(10000)):
...

Ich schrieb ein einfaches progressbar:

def bar(total, current, length=10, prefix="", filler="#", space=" ", oncomp="", border="[]", suffix=""):
    if len(border) != 2:
        print("parameter 'border' must include exactly 2 symbols!")
        return None

    print(prefix + border[0] + (filler * int(current / total * length) +
                                      (space * (length - int(current / total * length)))) + border[1], suffix, "\r", end="")
    if total == current:
        if oncomp:
            print(prefix + border[0] + space * int(((length - len(oncomp)) / 2)) +
                  oncomp + space * int(((length - len(oncomp)) / 2)) + border[1], suffix)
        if not oncomp:
            print(prefix + border[0] + (filler * int(current / total * length) +
                                        (space * (length - int(current / total * length)))) + border[1], suffix)

Wie Sie sehen, es hat: Länge der Bar, Präfix und Suffix, Füllstoff, Raum, Text in bar auf 100% (oncomp) und Grenzen

Hier ein Beispiel:

from time import sleep, time
start_time = time()
for i in range(10):
    pref = str((i+1) * 10) + "% "
    complete_text = "done in %s sec" % str(round(time() - start_time))
    sleep(1)
    bar(10, i + 1, length=20, prefix=pref, oncomp=complete_text)

out in progress:

30% [######              ]

heraus vollständig:

100% [   done in 9 sec   ] 
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top