Text Fortschrittsbalken in der Konsole [geschlossen]
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.)
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]
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
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]
- http://code.activestate.com/recipes/168639- Fortschrittsbalken-Klasse / (2002)
- http://code.activestate.com/ Rezepte / 299207-console-Text-progress-Indikator-Klasse / (2004)
- http://pypi.python.org/pypi/progressbar (2006)
Und viele Tutorials warten gegoogelt werden.
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
getlol 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
-
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
zuprog2 = 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 ]