شريط التقدم النص في وحدة التحكم [مغلق
سؤال
هل هناك طريقة جيدة للقيام بما يلي؟
لقد كتبت تطبيق وحدة تحكم بسيط لتحميل الملفات وتنزيلها من خادم FTP باستخدام FTPLIB.
في كل مرة يتم تنزيل بعض قطع البيانات ، أريد تحديث شريط تقدم النص ، حتى لو كان مجرد رقم.
لكني لا أريد محو كل النصوص التي تمت طباعتها على وحدة التحكم. (القيام "واضح" ثم طباعة النسبة المئوية المحدثة.)
المحلول
شريط تقدم بسيط وقابل للتخصيص
إليك مجموعة من الإجابات أدناه التي أستخدمها بانتظام (لا توجد واردات مطلوبة).
# 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()
ملحوظة: هذا لبيثون 3 ؛ انظر التعليقات للحصول على تفاصيل حول استخدام هذا في بيثون 2.
استخدام العينة
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)
إخراج العينة:
Progress: |█████████████████████████████████████████████-----| 90.0% Complete
تحديث
كان هناك نقاش في التعليقات المتعلقة بخيار يسمح لبرنامج التقدم بالضبط ديناميكيًا مع عرض النافذة الطرفية. على الرغم من أنني لا أوصي بهذا ، إليك ملف جوهر هذا ينفذ هذه الميزة (ويلاحظ المحاذير).
نصائح أخرى
ستنقل كتابة " r" المؤشر إلى بداية الخط.
هذا يعرض عداد النسبة المئوية:
import time
import sys
for i in range(100):
time.sleep(1)
sys.stdout.write("\r%d%%" % i)
sys.stdout.flush()
TQDM: أضف مقياس تقدم إلى حلقاتك في الثانية:
>>> 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]
اكتب \r
إلى وحدة التحكم. هذا هو "إرجاع" الذي يسبب كل النص بعد أن يتم صدىه في بداية الخط. شيء مثل:
def update_progress(progress):
print '\r[{0}] {1}%'.format('#'*(progress/10), progress)
الذي سيعطيك شيئًا مثل: [ ########## ] 100%
هو أقل من 10 أسطر من التعليمات البرمجية.
جوهر هنا: 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
جرب ال انقر مكتبة كتبها موزارت بيثون ، أرمين رونشر.
$ pip install click # both 2 and 3 compatible
لإنشاء شريط تقدم بسيط:
import click
with click.progressbar(range(1000000)) as bar:
for i in bar:
pass
هذا ما يبدو عليه:
# [###-------------------------------] 9% 00:01:14
تخصيص محتوى قلوبك:
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
نظرة مخصصة:
(_(_)===================================D(_(_| 100000/100000 00:00:02
هناك المزيد من الخيارات ، انظر مستندات API:
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)
أدرك أنني تأخرت عن اللعبة ، لكن إليك واحدة من طراز Yum (Hat Red Hat) التي كتبتها (لا أذهب إلى دقة 100 ٪ هنا ، ولكن إذا كنت تستخدم شريط تقدم لهذا المستوى من الدقة ، فأنت أنت 'إعادة خطأ على أي حال):
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()
يجب أن تنتج شيئًا يبدو مثل هذا:
Percent: [############## ] 69%
... حيث تبقى الأقواس ثابتة وفقط تجزئة يزداد.
هذا قد يعمل بشكل أفضل كديكور. ليوم آخر...
تحقق من هذه المكتبة: كلينت
لديها الكثير من الميزات بما في ذلك شريط التقدم:
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)
هذه حلقة الوصل يوفر نظرة عامة سريعة على ميزاته
إليكم مثالًا رائعًا على شريط تقدم مكتوب في بيثون: http://nadiana.com/animated-terminal-progress-bar-in-python
ولكن إذا كنت تريد أن تكتبها بنفسك. يمكنك استخدام curses
الوحدة لتسهيل الأمور :)
تحرير] ربما أسهل ليست كلمة اللعنات. ولكن إذا كنت ترغب في إنشاء CUI الكامل من اللعنات ، فإن العناية بالكثير من الأشياء لك.
تحرير] نظرًا لأن الرابط القديم قد مات ، فقد وضعت نسختي الخاصة من Python ProgressBar ، احصل عليها هنا: 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()
انتاج
[ 29% ] ===================
ولمجرد إضافة إلى الكومة ، إليك كائن يمكنك استخدامه
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"
النتائج في:
starting things:
100% [=================================================================]
done
سيكون هذا الأمر أكثر شيوعًا "على القمة" ، لكنه مفيد عندما تستخدمه كثيرًا
تشغيل هذا في سطر أوامر بيثون (ليس في أي IDE أو بيئة تنمية):
>>> import threading
>>> for i in range(50+1):
... threading._sleep(0.5)
... print "\r%3d" % i, ('='*i)+('-'*(50-i)),
يعمل بشكل جيد على نظام Windows الخاص بي.
تثبيت tqdm
.(pip install tqdm
) واستخدامه على النحو التالي:
import time
from tqdm import tqdm
for i in tqdm(range(1000)):
time.sleep(0.01)
هذا هو شريط التقدم 10 ثوانٍ سيؤدي إلى إخراج شيء من هذا القبيل:
47%|██████████████████▊ | 470/1000 [00:04<00:05, 98.61it/s]
- http://code.activestate.com/recipes/168639-progress-bar-class/ (2002)
- http://code.activestate.com/recipes/299207-console-text-progress-indicator-class/ (2004)
- http://pypi.python.org/pypi/ProgressBar (2006)
والكثير من البرامج التعليمية التي تنتظر أن تكون غوغل.
انا استخدم التقدم من رديت. يعجبني ذلك لأنه يمكن أن يطبع التقدم لكل عنصر في سطر واحد ، ويجب ألا يمحو المطبوعات من البرنامج.
تحرير: رابط ثابت
استنادًا إلى الإجابات المذكورة أعلاه وغيرها من الأسئلة المماثلة حول CLI Progress Bar ، أعتقد أنني حصلت على إجابة شائعة عامة على كل منها. تحقق من ذلك في https://stackoverflow.com/a/15860757/2254146
باختصار ، الرمز هو:
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()
يشبه
في المئة: [#########] 99.0 ٪
أوصي باستخدام TQDM - https://pypi.python.org/pypi/tqdm - مما يجعل من السهل تحويل أي أمر لا يطاق أو معالجة إلى شريط تقدم ، ويتعامل مع كل العبث مع المحطات المطلوبة.
من الوثائق: "يمكن لـ TQDM بسهولة دعم عمليات الاسترجاعات/السنانير والتحديثات اليدوية. إليك مثال مع 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)
حاول تثبيت هذه الحزمة: pip install progressbar2
:
import time
import progressbar
for i in progressbar.progressbar(range(100)):
time.sleep(0.02)
Progressbar 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()
ملاحظة: إذا قمت بتشغيل هذا في Intereactive Interpter ، فستحصل على أرقام إضافية مطبوعة
لول ، لقد كتبت للتو شيئًا كاملًا لهذه البدعة ، تضع الرمز في الاعتبار أنه لا يمكنك استخدام Unicode عند القيام بلوك ASCII ، أستخدم 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()
وأنت تسميها مثل ذلك
print "loading something awesome"
load("|", "|", 10, .01)
لذلك يبدو هكذا
loading something awesome
|█████ |
مع النصائح الرائعة أعلاه ، أعمل على شريط التقدم.
ومع ذلك أود أن أشير إلى بعض أوجه القصور
في كل مرة يتم فيها مسح شريط التقدم ، سيبدأ على خط جديد
print('\r[{0}]{1}%'.format('#' * progress* 10, progress))
مثله:
[] 0%
[#]10%
[##]20%
[###]30%
2. القوس المربع "] وعدد النسبة المئوية على الجانب الأيمن يمينًا حيث يزداد "###" لفترة أطول.
3. سيحدث خطأ إذا لم يتمكن التعبير "تقدم / 10" من إرجاع عدد صحيح.
وسيقوم الرمز التالي بإصلاح المشكلة أعلاه.
def update_progress(progress, total):
print('\r[{0:10}]{1:>2}%'.format('#' * int(progress * 10 /total), progress), end='')
الحل البسيط للغاية هو وضع هذا الرمز في حلقتك:
ضع هذا في الجسم (أي أعلى) من ملفك:
import sys
ضع هذا في جسم حلقتك:
sys.stdout.write("-") # prints a dash for each iteration of loop
sys.stdout.flush() # ensures bar is displayed incrementally
رمز شريط التقدم الطرفي بيثون
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()
وضع بعض الأفكار التي وجدتها هنا ، وإضافة الوقت المقدر المتبقي:
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)
حسنًا ، هنا رمز يعمل واختبرته قبل النشر:
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()
الايجابيات:
- 20 حرفًا (حرف واحد لكل 5 (رقم حكيمة))
- شخصيات ملء مخصصة
- أحرف فارغة مخصصة
- توقف (أي رقم أقل من 0)
- تم (100 وأي رقم فوق 100)
- عدد التقدم (0-100 (أدناه وما فوق يستخدم لوظائف خاصة))
- عدد النسبة المئوية بجانب الشريط ، وهو سطر واحد
سلبيات:
- يدعم الأعداد الصحيحة فقط (يمكن تعديلها لدعمهم ، من خلال جعل القسم تقسيم عدد صحيح ، لذلك فقط التغيير
prog2 = prog/5
إلىprog2 = int(prog/5)
)
ها هو حل بيثون 3 الخاص بي:
import time
for i in range(100):
time.sleep(1)
s = "{}% Complete".format(i)
print(s,end=len(s) * '\b')
' b' هو ملاذ خلفي ، لكل حرف في السلسلة الخاصة بك. هذا لا يعمل داخل نافذة Windows CMD.
وظيفة من Greenstick لمدة 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()
وحدة بيثون شريط التقدم هو اختيار لطيف. هذا هو الكود النموذجي الخاص بي:
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 هي مكتبة جيدة لـ ASCII Base ProgressBar لوقت استيراد سطر الأوامر
bar = progressbar.ProgressBar()
for i in bar(range(100)):
time.sleep(0.02)
bar.finish()
https://pypi.python.org/pypi/tqdm
TQDM هو بديل لـ ProgressBar2 وأعتقد أنه يستخدم في PIP3 لكنني لست متأكدًا من ذلك
from tqdm import tqdm
for i in tqdm(range(10000)):
...
لقد كتبت شريط تقدم بسيط:
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)
كما ترون ، يحتوي على: طول الشريط ، البادئة واللاحقة ، الحشو ، المساحة ، النص في الشريط على 100 ٪ (oncomp) والحدود
مثال هنا:
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)
في التقدم:
30% [###### ]
في الخارج:
100% [ done in 9 sec ]