it-swarm.com.de

Textfortschrittsleiste in der Konsole

Gibt es eine gute Möglichkeit, Folgendes zu tun?

Ich habe eine einfache Konsolen-App zum Hochladen und Herunterladen von Dateien von einem FTP-Server mit der ftplib geschrieben.

Jedes Mal, wenn einige Datenblöcke heruntergeladen werden, möchte ich eine Textfortschrittsanzeige aktualisieren, auch wenn es sich nur um eine Zahl handelt.

Ich möchte jedoch nicht den gesamten Text löschen, der auf der Konsole gedruckt wurde. (Machen Sie ein "clear" und drucken Sie dann den aktualisierten Prozentsatz.)

370
bobber205

Eine einfache, anpassbare Fortschrittsanzeige

Hier ist eine Zusammenfassung vieler der Antworten, die ich regelmäßig verwende (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: Dies ist für Python 3; Einzelheiten zur Verwendung in Python 2.

Beispielnutzung

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

Aktualisieren

In den Kommentaren wurde eine Option besprochen, mit der sich der Fortschrittsbalken dynamisch an die Breite des Terminalfensters anpassen lässt. Obwohl ich dies nicht empfehle, ist hier ein Gist , das diese Funktion implementiert (und die Vorbehalte beachtet).

343
Greenstick

Wenn Sie '\ r' schreiben, springt der Cursor an den Zeilenanfang.

Dies zeigt einen Prozentzähler an:

import time
import sys

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

tqdm: Füge in Sekundenschnelle eine Fortschrittsanzeige zu deinen Loops hinz :

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

153
jfs

Schreib ein \r an die Konsole. Dies ist ein "Wagenrücklauf" , das bewirkt, dass der gesamte Text am Zeilenanfang wiedergegeben wird. So etwas wie:

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

das gibt dir so etwas wie: [ ########## ] 100%

109
aviraldg

Es sind weniger als 10 Codezeilen.

Das Wesentliche hier: https://Gist.github.com/vladignatyev/06860ec2040cb497f0f

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

66

Probieren Sie die click Bibliothek, die von Mozart of Python, Armin Ronacher, geschrieben wurde.

$ pip install click # both 2 and 3 compatible

So erstellen Sie eine einfache Fortschrittsanzeige:

import click

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

So sieht es aus:

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

Fertigen Sie zu Ihrem Herzinhalt besonders an:

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

Benutzerdefiniertes Aussehen:

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

Es gibt noch mehr Optionen, siehe 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)
58
The Unfun Cat

Mir ist klar, dass ich zu spät zum Spiel komme, aber hier ist ein wenig Yum-Style (Red Hat), den ich geschrieben habe (hier wird nicht 100% Genauigkeit vorausgesetzt, aber wenn Sie einen Fortschrittsbalken für diese Genauigkeitsstufe verwenden, dann Sie sind sowieso FALSCH):

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 ungefähr so ​​aussehen:

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

... wo die Klammern stationär bleiben und nur die Hashes zunehmen.

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

32
JoeLinux

Überprüfen Sie diese Bibliothek: clint

es hat viele Funktionen, einschließlich einer Fortschrittsanzeige:

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

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

this link bietet einen schnellen Überblick über seine Funktionen

17
scripts

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

Aber wenn du es selbst schreiben willst. Sie können das curses -Modul verwenden, um die Dinge einfacher zu machen :)

[edit] Vielleicht ist das Wort für Flüche nicht einfacher. Aber wenn Sie eine ausgewachsene Cui erstellen möchten, erledigt Curses eine Menge für Sie.

[Bearbeiten] Da der alte Link nicht mehr funktioniert, habe ich eine eigene Version einer Python Progressbar erstellt, die Sie hier herunterladen können: https://github.com/WoLpH/python- Fortschrittsbalken

12
Wolph
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()

ausgabe

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

10
ashish2py

und, nur um den Stapel zu vergrößern, hier ist ein Objekt, das Sie verwenden können

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 __== "__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 wird am häufigsten als "übertrieben" angesehen, ist jedoch praktisch, wenn Sie es häufig verwenden

7
FraggaMuffin

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

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

Das ist eine 10-Sekunden-Fortschrittsanzeige, die etwa Folgendes ausgibt:

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

Führen Sie dieses in der Python Befehlszeile (nicht in einem beliebigen IDE oder Entwicklungsumgebung):

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

Funktioniert gut auf meinem Windows-System.

6
PaulMcG

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

Bearbeiten: fester Link

4
Ib33X
4

aufgrund der obigen Antworten und anderer ähnlicher Fragen zum CLI-Fortschrittsbalken habe ich wahrscheinlich eine allgemeine gemeinsame Antwort auf alle Fragen erhalten. Überprüfen Sie es unter https://stackoverflow.com/a/15860757/2254146

Zusammenfassend 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

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

3
Brian Khuu

Ich empfehle die Verwendung von tqdm - https://pypi.python.org/pypi/tqdm -, was es einfach macht, jedes iterative oder prozessbasierte Element in einen Fortschrittsbalken zu verwandeln, und das ganze Herumspielen mit den benötigten Terminals erledigt.

Aus der Dokumentation: "tqdm kann Callbacks/Hooks und manuelle Updates problemlos unterstützen. 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)
3
Malcolm Box

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

3
Chris Cui

lol ich habe gerade ein ganzes Ding für dieses hieres geschrieben der Code denkt daran, dass Sie Unicode nicht verwenden können, wenn Sie Block Ascii tun, das ich cp437 benutze

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 du nennst es so

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

so sieht es also aus

loading something awesome
|█████     |
2
ryan

Mit den oben genannten tollen Ratschlägen erarbeite ich den Fortschrittsbalken.

Ich möchte jedoch auf einige Mängel hinweisen

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

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

    so was:
    [] 0%
    [#] 10%
    [##] 20%
    [###] 30%

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

Der folgende Code behebt das oben beschriebene Problem.

def update_progress(progress, total):  
    print('\r[{0:10}]{1:>2}%'.format('#' * int(progress * 10 /total), progress), end='')
2
Storm-Eyes
import sys
def progresssbar():
         for i in range(100):
            time.sleep(1)
            sys.stdout.write("%i\r" % i)

progressbar()

HINWEIS: Wenn Sie dies im interaktiven Interpreter ausführen, werden zusätzliche Zahlen ausgedruckt

2
Ramchandra Apte

Eine sehr einfache Lösung besteht darin, diesen Code in Ihre Schleife einzufügen:

Fügen Sie dies in den Text (d. H. Oben) Ihrer Datei ein:

import sys

Fügen Sie dies in den Text Ihrer Schleife ein:

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

Einige der Ideen, die ich hier gefunden habe, zusammenstellen und die geschätzte verbleibende Zeit hinzufügen:

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)
1
Ivan Chaer

Code für python terminal progress bar

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()
1
emd_22

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 Backslash für jedes Zeichen in Ihrer Zeichenfolge. Dies funktioniert nicht im Windows-Cmd-Fenster.

0
Matt-the-Bat

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

Progressbar2 ist eine gute Bibliothek für den ASCII-Basisfortschrittsbalken für den Fortschrittsbalken für den Import der Befehlszeilen-Importzeit

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 zu progressbar2 und ich denke, es wird in pip3 verwendet, aber ich bin mir nicht sicher

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

Hier ist der Code, der funktioniert und den ich vor dem Posten getestet habe:

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-stellige Leiste (1 Zeichen für jeweils 5 (zahlenweise))
  • Benutzerdefinierte Füllzeichen
  • Benutzerdefinierte leere Zeichen
  • Halt (jede Zahl unter 0)
  • Fertig (100 und eine beliebige Zahl über 100)
  • Fortschrittszahl (0-100 (unten und oben für Sonderfunktionen verwendet))
  • Prozentzahl neben dem Balken, und es ist eine einzelne Zeile

Nachteile:

  • Unterstützt nur Ganzzahlen (Sie können diese jedoch ändern, indem Sie die Division zu einer Ganzzahldivision machen. Ändern Sie also einfach prog2 = prog/5 In prog2 = int(prog/5).)
0
Cold Diamondz

funktion von Greenstick 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()

Für python 3:

def progress_bar(current_value, total):
    increments = 50
    percentual = ((current_value/ total) * 100)
    i = int(percentual // (100 / increments ))
    text = "\r[{0: <{1}}] {2}%".format('=' * i, increments, percentual)
    print(text, end="\n" if percentual == 100 else "")
0
Rodrigo López

Das python Modul Fortschrittsbalken 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()
0
Aimin Huang

ich habe einen einfachen Fortschrittsbalken geschrieben:

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 können, hat es: Länge des Strichs, Präfix und Suffix, Füllzeichen, Leerzeichen, Text in Strich auf 100% (oncomp) und Rahmen

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)

in Bearbeitung:

30% [######              ]

fertig:

100% [   done in 9 sec   ] 
0
jenkins