Панель прогресу Python


307

Як використовувати панель прогресу, коли мій сценарій виконує якесь завдання, яке, ймовірно, потребує часу?

Наприклад, функція, яка потребує певного часу для завершення та повертається Trueпісля її виконання. Як я можу відобразити панель прогресу під час виконання функції?

Зауважте, що мені це потрібно в режимі реального часу, тому я не можу зрозуміти, що з цим робити. Чи потрібно мені threadдля цього? Я поняття не маю.

Зараз я нічого не друкую під час виконання функції, однак смужка прогресу була б непоганою. Також мене більше цікавить, як це можна зробити з кодової точки зору.


Ви використовуєте лише інструментарій GUI або CLI?
Боббі

CLI. Але я можу використати сторонні бібліотеки, це не проблема. За допомогою GUI я можу це зробити, але мене зацікавила частина CLI.
user225312

1
Можливий дублікат панелі прогресу тексту в консолі. Зауважте, що хоч це питання було розміщено на три дні раніше, пов'язане питання частіше переглядається.
Greenstick

Ось рішення для ноутбука Юпітера
Стівен К. Хоуелл

Я опублікував новий вид смужки прогресу, який можна надрукувати, побачити пропускну здатність та ета, навіть призупинити його, окрім дуже крутих анімацій! Погляньте: github.com/rsalmei/alive-progress !
live

Відповіді:


185

Існують певні бібліотеки ( як ця тут ), але, можливо, щось дуже просте:

import time
import sys

toolbar_width = 40

# setup toolbar
sys.stdout.write("[%s]" % (" " * toolbar_width))
sys.stdout.flush()
sys.stdout.write("\b" * (toolbar_width+1)) # return to start of line, after '['

for i in xrange(toolbar_width):
    time.sleep(0.1) # do real work here
    # update the bar
    sys.stdout.write("-")
    sys.stdout.flush()

sys.stdout.write("]\n") # this ends the progress bar

Примітка: progressbar2 - це вилка панелі прогресу, яка не підтримується роками.


14
це не масштабує багато кроків ... pypi.python.org/pypi/progress набагато простіше у використанні
m13r

5
Я спробував цей код, і він видав NameError: name 'xrange' is not definedпомилку. Я пропускаю модуль?
Грибний Людина

6
@ GokuMcSpock9733 Яку версію Python ви використовуєте? Python's 2 xrange- це Python's 3 range.
quapka

9
Це не повинно бути головною відповіддю. Інша відповідь (з tqdm) набагато краща для мене, принаймні.
Флоріан

1
Прогрес для бідних у Python 3:print('■', end='', flush=True)
PatrickT

351

За допомогою tqdm ви можете додати метр прогресу до циклів за секунду:

In [1]: import time

In [2]: from tqdm import tqdm

In [3]: for i in tqdm(range(10)):
   ....:     time.sleep(3)

 60%|██████    | 6/10 [00:18<00:12,  0.33 it/s]

Також є графічна версія tqdm since v2.0.0( d977a0c):

In [1]: import time

In [2]: from tqdm import tqdm_gui

In [3]: for i in tqdm_gui(range(100)):
  ....:     time.sleep(3)

вікно tqdm gui

Але будьте обережні, оскільки tqdm_guiможете підняти a TqdmExperimentalWarning: GUI is experimental/alpha, ви можете проігнорувати його, використовуючи warnings.simplefilter("ignore"), але після цього він буде ігнорувати всі попередження у вашому коді.


9
Це єдине рішення , яке я знайшов для роботи з терміналом, qtconsole і ноутбук
Івелін

3
Це працює з будь-яким ітерабельним? У мене виникли проблеми з його роботою зі списком рядків.
Josh Usre

3
@JoshUsre Так, це повинно працювати з будь-яким ітерабельним, на даний момент я не бачив жодного ітеративного, на якому він задихався. Однак для відображення ETA (час, що залишився) вимагає, щоб ітерабельність мав __len__властивість, або користувач повинен надати totalаргумент tqdm. Інакше, бар працюватиме, але без ETA.
габоровий

6
@gaborous: Чому це не найкраща відповідь? Це просте рішення працює як в терміналі, так і в ноутбуці Юпітера на відміну від верхньої відповіді.
Ібе Ісаак

6
для запуску в користування ноутбуком з юпітером from tqdm import tqdm_notebook as tqdm. Інакше не пише це на одному рядку.
Жак МАЛАПРЕЙД

81

Наведені вище пропозиції є досить гарними, але я думаю, що більшість людей просто хочуть готового рішення, не залежно від зовнішніх пакунків, але також є багаторазовим.

Я отримав найкращі бали з усього вищезазначеного та перетворив його на функцію разом із тестовими кейсами.

Щоб використовувати його, просто скопіюйте рядки під "def update_progress (progress)", але не тестовий сценарій. Не забудьте імпортувати sys. Зателефонуйте цьому, коли потрібно відобразити або оновити панель прогресу.

Це працює, безпосередньо надсилаючи символ "\ r" на консоль, щоб перемістити курсор назад до початку. "print" у python не перекомпонує вищевказаний символ для цієї мети, отже, нам знадобиться "sys"

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


# update_progress test script
print "progress : 'hello'"
update_progress("hello")
time.sleep(1)

print "progress : 3"
update_progress(3)
time.sleep(1)

print "progress : [23]"
update_progress([23])
time.sleep(1)

print ""
print "progress : -10"
update_progress(-10)
time.sleep(2)

print ""
print "progress : 10"
update_progress(10)
time.sleep(2)

print ""
print "progress : 0->1"
for i in range(101):
    time.sleep(0.1)
    update_progress(i/100.0)

print ""
print "Test completed"
time.sleep(10)

Ось що показує результат тестового сценарію (Оновлення останнього рядка прогресу):

progress : 'hello'
Percent: [----------] 0% error: progress var must be float
progress : 3
Percent: [##########] 100% Done...
progress : [23]
Percent: [----------] 0% error: progress var must be float

progress : -10
Percent: [----------] 0% Halt...

progress : 10
Percent: [##########] 100% Done...

progress : 0->1
Percent: [##########] 100% Done...
Test completed

10
Анімований тест (останній) повинен говорити in range(101)не 100, прогрес зупиняється на 99% і ніколи не відображається зроблено.
Нік Гумріч

41

Ця відповідь не покладається на зовнішні пакунки , я також думаю, що більшість людей просто хочуть готовий фрагмент коду . Наведений нижче код можна адаптувати відповідно до ваших потреб, налаштовуючи: символ прогресу '#'смужки size, смугу , текст prefixтощо.

import sys

def progressbar(it, prefix="", size=60, file=sys.stdout):
    count = len(it)
    def show(j):
        x = int(size*j/count)
        file.write("%s[%s%s] %i/%i\r" % (prefix, "#"*x, "."*(size-x), j, count))
        file.flush()        
    show(0)
    for i, item in enumerate(it):
        yield item
        show(i+1)
    file.write("\n")
    file.flush()

Використання:

import time

for i in progressbar(range(15), "Computing: ", 40):
    time.sleep(0.1) # any calculation you need

Вихід:

Computing: [################........................] 4/15
  • Не потрібен другий потік . Деякі рішення / пакети вище вимагають. Наприклад, друга нитка може бути проблемою jupyter notebook.

  • Працює з будь-яким ітерабельним, це означає все, що len()можна використовувати. A list, що dict-небудь, наприклад['a', 'b', 'c' ... 'g']

Ви також можете змінити висновок, змінивши файл sys.stderr, наприклад


Мені подобається це рішення, генератори викинуть таку помилку:TypeError: object of type 'generator' has no len()
jabellcu

@jabellcu у цьому випадку ( generators) ви повинні обгорнути його list(). Якfor i in progressbar(list(your_generator), "Computing: ", 40):
eusoubrasileiro

22

для аналогічного додатка (відстеження прогресу в циклі) я просто використав панель python-progress :

Їх приклад іде приблизно так,

from progressbar import *               # just a simple progress bar


widgets = ['Test: ', Percentage(), ' ', Bar(marker='0',left='[',right=']'),
           ' ', ETA(), ' ', FileTransferSpeed()] #see docs for other options

pbar = ProgressBar(widgets=widgets, maxval=500)
pbar.start()

for i in range(100,500+1,50):
    # here do something long at each iteration
    pbar.update(i) #this adds a little symbol at each iteration
pbar.finish()
print

3
Для сумісності Python 3 спробуйте отримати progressbar2пакет. Код, наведений вище, буде працювати з ним.
d33tah

2
Ви справді просто використовували import *?
eric

20

Спробуйте досягти успіху на https://pypi.python.org/pypi/progress .

from progress.bar import Bar

bar = Bar('Processing', max=20)
for i in range(20):
    # Do some work
    bar.next()
bar.finish()

У результаті вийде смужка на зразок наступного:

Processing |#############                   | 42/100

Просто спробував це. ДУЖЕ простий у використанні. Мені потрібні дві хвилини (включаючи прогрес встановлення файлів), щоб мати статус і працювати.
перелин

progressробить непогані бари, але виходить з ладу, якщо інше програмне забезпечення маніпулює stderr. вибачте, але я не дослідив точну проблему.
Артур

Він друкує один рядок для кожного прогресу в моїй консолі ubuntu, наприклад, якщо max = 20, він друкує 20 рядків ... Як зробити так, щоб він друкував лише один рядок?
Світ L

19

Щойно я створив простий клас прогресу для своїх потреб, шукаючи тут рівнозначне рішення. Я подумав, що, можливо, це викладу.

from __future__ import print_function
import sys
import re


class ProgressBar(object):
    DEFAULT = 'Progress: %(bar)s %(percent)3d%%'
    FULL = '%(bar)s %(current)d/%(total)d (%(percent)3d%%) %(remaining)d to go'

    def __init__(self, total, width=40, fmt=DEFAULT, symbol='=',
                 output=sys.stderr):
        assert len(symbol) == 1

        self.total = total
        self.width = width
        self.symbol = symbol
        self.output = output
        self.fmt = re.sub(r'(?P<name>%\(.+?\))d',
            r'\g<name>%dd' % len(str(total)), fmt)

        self.current = 0

    def __call__(self):
        percent = self.current / float(self.total)
        size = int(self.width * percent)
        remaining = self.total - self.current
        bar = '[' + self.symbol * size + ' ' * (self.width - size) + ']'

        args = {
            'total': self.total,
            'bar': bar,
            'current': self.current,
            'percent': percent * 100,
            'remaining': remaining
        }
        print('\r' + self.fmt % args, file=self.output, end='')

    def done(self):
        self.current = self.total
        self()
        print('', file=self.output)

Приклад:

from time import sleep

progress = ProgressBar(80, fmt=ProgressBar.FULL)

for x in xrange(progress.total):
    progress.current += 1
    progress()
    sleep(0.1)
progress.done()

Буде надруковано наступне:

[======== ] 17/80 ( 21%) 63 to go


3
Дивовижне, дякую за це. До речі, ви можете додати progress.currentзбільшення в кінці, __call__щоб ще більше обмежити взаємодію з об'єктом з основного коду.
npit

Цей код простий, стислий і корисний! Дякую!
Ян Рехвінкель

15

Мені подобається відповідь Брайана Кху за її простоту і не потребує зовнішніх пакунків. Я трохи змінив його, тому додаю сюди свою версію:

import sys
import time


def updt(total, progress):
    """
    Displays or updates a console progress bar.

    Original source: https://stackoverflow.com/a/15860757/1391441
    """
    barLength, status = 20, ""
    progress = float(progress) / float(total)
    if progress >= 1.:
        progress, status = 1, "\r\n"
    block = int(round(barLength * progress))
    text = "\r[{}] {:.0f}% {}".format(
        "#" * block + "-" * (barLength - block), round(progress * 100, 0),
        status)
    sys.stdout.write(text)
    sys.stdout.flush()


runs = 300
for run_num in range(runs):
    time.sleep(.1)
    updt(runs, run_num + 1)

Це займає загальну кількість запусків ( total) та кількість запущених циклів ( progress), припускаючи total >= progress. Результат виглядає приблизно так:

[#####---------------] 27%

14

Ви можете використовувати tqdm :

from tqdm import tqdm

with tqdm(total=100, desc="Adding Users", bar_format="{l_bar}{bar} [ time left: {remaining} ]") as pbar:
    for i in range(100):
        time.sleep(3)
        pbar.update(1)

У цьому прикладі панель прогресу працює протягом 5 хвилин, і це показано так:

Adding Users:   3%|█████▊                                     [ time left: 04:51 ]                                                                                                        

Ви можете змінити його та налаштувати за своїм бажанням.


11

Щоб корисно використовувати будь-які рамки смуги прогресу, тобто отримати фактичний відсоток прогресу та розрахунковий показник ETA, ви повинні мати можливість оголосити, скільки кроків у нього буде.

Отже, ваша обчислювальна функція в іншому потоці, чи можете ви розділити її на кілька логічних етапів? Чи можете ви змінити його код?

Вам не потрібно рефакторировать його або розділяти фактичними методами, ви можете просто поставити деякі стратегічні yieldмісця десь усередині нього! Якщо у дорогої функції є цикл for , просто покладіть її. Вам слід лише знати наприкінці, скільки врожаїв буде зроблено, щоб отримати найкращі результати.

Таким чином, ваша функція може бути приблизно такою:

def compute():
    time.sleep(1)  # some processing here
    yield  # insert these
    time.sleep(1)
    yield
    time.sleep(1)
    yield

або це:

def compute():
    for i in range(1000):
        time.sleep(.1)  # some processing here
        yield  # insert these

За допомогою такої функції ви можете встановити:

pip install alive-progress

І використовувати його так:

from alive_progress import alive_bar

with alive_bar(3) as bar:  # or a 1000 in the loop example.
    for i in compute():
        bar()

Щоб отримати класний прогрес-бар!

|█████████████▎                          | ▅▃▁ 1/3 [33%] in 1s (1.0/s, eta: 2s)

Відмова: Я автор "live_progress", але це повинно добре вирішити вашу проблему. Прочитайте документацію на веб- сайті https://github.com/rsalmei/alive-progress , ось приклад того, що вона може зробити:

живий-прогрес


8

Мені дуже подобається панель python-progress , оскільки це дуже просте у використанні.

Для найпростішого випадку це просто:

import progressbar
import time

progress = progressbar.ProgressBar()
for i in progress(range(80)):
    time.sleep(0.01)

Зовнішній вигляд можна налаштувати, і він може відображати передбачуваний час. Для прикладу використовуйте той самий код, що і вище, але з:

progress = progressbar.ProgressBar(widgets=[progressbar.Bar('=', '[', ']'), ' ',
                                            progressbar.Percentage(), ' ',
                                            progressbar.ETA()])

5

Якщо це великий цикл з фіксованою кількістю ітерацій, який займає багато часу, ви можете використовувати цю функцію, яку я зробив. Кожна ітерація циклу додає прогресу. Там, де підрахунок - це поточна ітерація циклу, загальна величина, яку ви петете, а розмір (int) - наскільки велика ви хочете смугу з кроком 10, тобто (розмір 1 = 10 символів, розмір 2 = 20 символів)

import sys
def loadingBar(count,total,size):
    percent = float(count)/float(total)*100
    sys.stdout.write("\r" + str(int(count)).rjust(3,'0')+"/"+str(int(total)).rjust(3,'0') + ' [' + '='*int(percent/10)*size + ' '*(10-int(percent/10))*size + ']')

приклад:

for i in range(0,100):
     loadingBar(i,100,2)
     #do some code 

вихід:

i = 50
>> 050/100 [==========          ]

4

Використовуйте цю бібліотеку: fish( GitHub ).

Використання:

>>> import fish
>>> while churning:
...     churn_churn()
...     fish.animate()

Весело!


Це можливо. Вам слід запитати розробника або залишити квиток: github.com/lericson/fish .
Етьєн

4

Нижче наведений код є досить загальним рішенням, а також має підрахунок часу та часу, що залишився. Ви можете використовувати будь-який ітерабельний з ним. Рядок прогресу має фіксований розмір 25 символів, але він може показувати оновлення кроками 1%, використовуючи символи повного, половинного та четвертого блоку. Вихід виглядає приблизно так:

 18% |████▌                    | \ [0:00:01, 0:00:06]

Код з прикладом:

import sys, time
from numpy import linspace

def ProgressBar(iterObj):
  def SecToStr(sec):
    m, s = divmod(sec, 60)
    h, m = divmod(m, 60)
    return u'%d:%02d:%02d'%(h, m, s)
  L = len(iterObj)
  steps = {int(x):y for x,y in zip(linspace(0, L, min(100,L), endpoint=False),
                                   linspace(0, 100, min(100,L), endpoint=False))}
  qSteps = ['', u'\u258E', u'\u258C', u'\u258A'] # quarter and half block chars
  startT = time.time()
  timeStr = '   [0:00:00, -:--:--]'
  activity = [' -',' \\',' |',' /']
  for nn,item in enumerate(iterObj):
    if nn in steps:
      done = u'\u2588'*int(steps[nn]/4.0)+qSteps[int(steps[nn]%4)]
      todo = ' '*(25-len(done))
      barStr = u'%4d%% |%s%s|'%(steps[nn], done, todo)
    if nn>0:
      endT = time.time()
      timeStr = ' [%s, %s]'%(SecToStr(endT-startT),
                             SecToStr((endT-startT)*(L/float(nn)-1)))
    sys.stdout.write('\r'+barStr+activity[nn%4]+timeStr); sys.stdout.flush()
    yield item
  barStr = u'%4d%% |%s|'%(100, u'\u2588'*25)
  timeStr = '   [%s, 0:00:00]\n'%(SecToStr(time.time()-startT))
  sys.stdout.write('\r'+barStr+timeStr); sys.stdout.flush()

# Example
s = ''
for c in ProgressBar(list('Disassemble and reassemble this string')):
  time.sleep(0.2)
  s += c
print(s)

Пропозиції щодо вдосконалення чи інші коментарі оцінюються. Ура!


3

Мені подобається ця сторінка .

Починається з простого прикладу і переходить до багатопотокової версії. Працює поза коробкою. Не потрібно сторонніх пакетів.

Код буде виглядати приблизно так:

import time
import sys

def do_task():
    time.sleep(1)

def example_1(n):
    for i in range(n):
        do_task()
        print '\b.',
        sys.stdout.flush()
    print ' Done!'

print 'Starting ',
example_1(10)

Або ось приклад використання потоків для запуску прядильної панелі завантаження під час роботи програми:

import sys
import time
import threading

class progress_bar_loading(threading.Thread):

    def run(self):
            global stop
            global kill
            print 'Loading....  ',
            sys.stdout.flush()
            i = 0
            while stop != True:
                    if (i%4) == 0: 
                        sys.stdout.write('\b/')
                    elif (i%4) == 1: 
                        sys.stdout.write('\b-')
                    elif (i%4) == 2: 
                        sys.stdout.write('\b\\')
                    elif (i%4) == 3: 
                        sys.stdout.write('\b|')

                    sys.stdout.flush()
                    time.sleep(0.2)
                    i+=1

            if kill == True: 
                print '\b\b\b\b ABORT!',
            else: 
                print '\b\b done!',


kill = False      
stop = False
p = progress_bar_loading()
p.start()

try:
    #anything you want to run. 
    time.sleep(1)
    stop = True
except KeyboardInterrupt or EOFError:
         kill = True
         stop = True

3

Це досить просто в Python3:

   import time
   import math

    def show_progress_bar(bar_length, completed, total):
        bar_length_unit_value = (total / bar_length)
        completed_bar_part = math.ceil(completed / bar_length_unit_value)
        progress = "*" * completed_bar_part
        remaining = " " * (bar_length - completed_bar_part)
        percent_done = "%.2f" % ((completed / total) * 100)
        print(f'[{progress}{remaining}] {percent_done}%', end='\r')

    bar_length = 30
    total = 100
    for i in range(0, total + 1):
        show_progress_bar(bar_length, i, total)
        time.sleep(0.1)

    print('\n')

3

Під час роботи в ноутбуках з юпітером використання звичайного tqdm не працює, оскільки він записує вихід у декілька рядків. Використовуйте це замість:

import time
from tqdm import tqdm_notebook as tqdm

for i in tqdm(range(100))
    time.sleep(0.5)

2

Якщо ваша робота не може бути розбита на вимірювані шматки, ви можете зателефонувати на свою функцію в новій нитці та час, який це займе:

import thread
import time
import sys

def work():
    time.sleep( 5 )

def locked_call( func, lock ):
    lock.acquire()
    func()
    lock.release()

lock = thread.allocate_lock()
thread.start_new_thread( locked_call, ( work, lock, ) )

# This part is icky...
while( not lock.locked() ):
    time.sleep( 0.1 )

while( lock.locked() ):
    sys.stdout.write( "*" )
    sys.stdout.flush()
    time.sleep( 1 )
print "\nWork Done"

Ви, очевидно, можете збільшити точність синхронізації за необхідності.


Де можна було б виконати роботу, яку слід виміряти у коді у відповідь?
unseen_rider

2

Мені подобається відповідь Габріеля , але я змінив її на гнучку. Ви можете надіслати функцію довжини смуги та отримати смужку ходу будь-якої потрібної вам довжини. І ви не можете мати смугу прогресу з нульовою або негативною довжиною. Крім того, ви можете використовувати цю функцію, як відповідь Габріеля (Дивіться приклад №2).

import sys
import time

def ProgressBar(Total, Progress, BarLength=20, ProgressIcon="#", BarIcon="-"):
    try:
        # You can't have a progress bar with zero or negative length.
        if BarLength <1:
            BarLength = 20
        # Use status variable for going to the next line after progress completion.
        Status = ""
        # Calcuting progress between 0 and 1 for percentage.
        Progress = float(Progress) / float(Total)
        # Doing this conditions at final progressing.
        if Progress >= 1.:
            Progress = 1
            Status = "\r\n"    # Going to the next line
        # Calculating how many places should be filled
        Block = int(round(BarLength * Progress))
        # Show this
        Bar = "[{}] {:.0f}% {}".format(ProgressIcon * Block + BarIcon * (BarLength - Block), round(Progress * 100, 0), Status)
        return Bar
    except:
        return "ERROR"

def ShowBar(Bar):
    sys.stdout.write(Bar)
    sys.stdout.flush()

if __name__ == '__main__':
    print("This is a simple progress bar.\n")

    # Example #1:
    print('Example #1')
    Runs = 10
    for i in range(Runs + 1):
        progressBar = "\rProgress: " + ProgressBar(10, i, Runs)
        ShowBar(progressBar)
        time.sleep(1)

    # Example #2:
    print('\nExample #2')
    Runs = 10
    for i in range(Runs + 1):
        progressBar = "\rProgress: " + ProgressBar(10, i, 20, '|', '.')
        ShowBar(progressBar)
        time.sleep(1)

    print('\nDone.')

# Example #2:
Runs = 10
for i in range(Runs + 1):
    ProgressBar(10, i)
    time.sleep(1)

Результат:

Це проста панель прогресу.

Приклад №1

Прогрес: [### -------] 30%

Приклад №2

Прогрес: [|||||||||||| ........] 60%

Зроблено.


2

Я використовував format()метод для виготовлення навантаження бар. Ось моє рішення:

import time

loadbarwidth = 23

for i in range(1, loadbarwidth + 1):
    time.sleep(0.1) 

    strbarwidth = '[{}{}] - {}\r'.format(
        (i * '#'),
        ((loadbarwidth - i) * '-'),
        (('{:0.2f}'.format(((i) * (100/loadbarwidth))) + '%'))
    )

    print(strbarwidth ,end = '')

print()

Вихід:

[#######################] - 100.00%

1

Ось коротке рішення, яке програмно будує панель завантаження (ви повинні вирішити, скільки часу ви хочете).

import time

n = 33  # or however many loading slots you want to have
load = 0.01  # artificial loading time!
loading = '.' * n  # for strings, * is the repeat operator

for i in range(n+1):
    # this loop replaces each dot with a hash!
    print('\r%s Loading at %3d percent!' % (loading, i*100/n), end='')
    loading = loading[:i] + '#' + loading[i+1:]
    time.sleep(load)

1

Спробуйте PyProg. PyProg - це бібліотека з відкритим кодом для Python для створення супер настроюваних індикаторів прогресу та барів.

Наразі він знаходиться у версії 1.0.2; він розміщений на Github та доступний на PyPI (Посилання нижче). Він сумісний з Python 3 & 2 і також може використовуватися з консоллю Qt.

Це дуже просто у використанні. Наступний код:

import pyprog
from time import sleep

# Create Object
prog = pyprog.ProgressBar(" ", "", 34)
# Update Progress Bar
prog.update()

for i in range(34):
    # Do something
    sleep(0.1)
    # Set current status
    prog.set_stat(i + 1)
    # Update Progress Bar again
    prog.update()

# Make the Progress Bar final
prog.end()

буде виробляти:

Initial State:
Progress: 0% --------------------------------------------------

When half done:
Progress: 50% #########################-------------------------

Final State:
Progress: 100% ##################################################

Насправді я створив PyProg, тому що мені потрібна була проста, але супер налаштована бібліотека бар прогресу. Ви можете легко встановити його за допомогою:pip install pyprog .

PyProg Github: https://github.com/Bill13579/pyprog
PyPI: https://pypi.python.org/pypi/pyprog/


1

Також можна використовувати просвітлити . Основна перевага полягає в тому, що ви можете одночасно входити в систему, не перезаписуючи панель ходу.

import time
import enlighten

manager = enlighten.Manager()
pbar = manager.counter(total=100)

for num in range(1, 101):
    time.sleep(0.05)
    print('Step %d complete' % num)
    pbar.update()

Він також обробляє декілька смуг прогресу.

import time
import enlighten

manager = enlighten.Manager()
odds = manager.counter(total=50)
evens = manager.counter(total=50)

for num in range(1, 101):
    time.sleep(0.05)
    if num % 2:
        odds.update()
    else:
        evens.update()

1

Використовуйте бібліотеку прогресу !

pip install progress

Ось спеціальний підклас, який я написав для форматування ETA / Elapsed разів у кращий для читання формат:

import datetime
from progress.bar import IncrementalBar


class ProgressBar(IncrementalBar):
    '''
    My custom progress bar that:
       - Show %, count, elapsed, eta
       - Time is shown in H:M:S format
    '''

    message = 'Progress'
    suffix  = '%(percent).1f%% (%(index)d/%(max)d) -- %(elapsed_min)s (eta: %(eta_min)s)'

    def formatTime(self, seconds):
        return str(datetime.timedelta(seconds=seconds))

    @property
    def elapsed_min(self):
        return self.formatTime(self.elapsed)

    @property
    def eta_min(self):
        return self.formatTime(self.eta)

if __name__=='__main__':
    counter = 120
    bar     = ProgressBar('Processing', max=counter)

    for i in range(counter):
        bar.next()
        time.sleep(1)

    bar.finish()

1

Це моє просте рішення:

import time

def progress(_cur, _max):
    p = round(100*_cur/_max)
    b = f"Progress: {p}% - ["+"."*int(p/5)+" "*(20-int(p/5))+"]"
    print(b, end="\r")

# USAGE:
for i in range(0,101):
    time.sleep(0.1) 
    progress(i,100)

print("..."*5, end="\r")
print("Done")

0

Ви повинні зв’язати смужку прогресу із заданою задачею (щоб вона вимірювала хід виконання: D). Наприклад, якщо ви FTPing файл, ви можете сказати ftplib, щоб захопити певний розмір буфера, скажімо, 128K, а потім ви додасте на панель прогресу незалежно від відсотка розміру файлу, який становить 128k. Якщо ви використовуєте CLI, а ваш показник прогресу становить 20 символів, ви додасте один символ, коли 1/20 файлу передано.


У моєму випадку я використовую API, і він не дає можливості отримувати конкретні шматки. Дякую за ідею, проте, це приємно.
user225312

0

@Massagran: Це добре працює в моїх програмах. Крім того, нам потрібно додати лічильник, щоб вказати час циклу. Цей лічильник грає як аргумент методу update. Наприклад: прочитайте всі рядки тестового файлу і обробіть їх на чомусь. Припустимо, що функція dosth()не стосується змінної i.

lines = open(sys.argv[1]).readlines()
i = 0
widgets=[Percentage(), Bar()]
pbar = ProgressBar(widgets=widgets,maxval=len(lines)).start()
pbar.start()
for line in lines:<pre>
    dosth();
    i += 1
    pbar.update(i)</pre>
pbar.finish()

Змінна iконтролює стан pbarчерез методupdate


0

трохи більш загальна відповідь від jelde015 (заслуга йому звичайно)

для оновлення панелі завантаження вручну буде:

import sys
from math import *


def loadingBar(i, N, size):
    percent = float(i) / float(N)
    sys.stdout.write("\r"
                     + str(int(i)).rjust(3, '0')
                     +"/"
                     +str(int(N)).rjust(3, '0')
                     + ' ['
                     + '='*ceil(percent*size)
                     + ' '*floor((1-percent)*size)
                     + ']')

і називає це:

loadingBar(7, 220, 40)

результат:

007/220 [=                                       ]  

просто зателефонуйте, коли хочете, з поточним i значенням.

встановіть sizeяк число символів, яким має бути бар


0

Здогадуюсь, я запізнююся, але це має працювати для людей, які працюють з поточними версіями python 3 , оскільки для цього використовуються "f-рядки" , як це було представлено в Python 3.6 PEP 498 :

Код

from numpy import interp

class Progress:
    def __init__(self, value, end, title='Downloading',buffer=20):
        self.title = title
        #when calling in a for loop it doesn't include the last number
        self.end = end -1
        self.buffer = buffer
        self.value = value
        self.progress()

    def progress(self):
        maped = int(interp(self.value, [0, self.end], [0, self.buffer]))
        print(f'{self.title}: [{"#"*maped}{"-"*(self.buffer - maped)}]{self.value}/{self.end} {((self.value/self.end)*100):.2f}%', end='\r')

Приклад

#some loop that does perfroms a task
for x in range(21)  #set to 21 to include until 20
    Progress(x, 21)

Вихідні дані

Downloading: [########------------] 8/20 40.00%

0

Це простий спосіб створити панель прогресу

import time,sys
toolbar_width = 50
# setting up toolbar [-------------------------------------]
sys.stdout.write("[%s]"%(("-")*toolbar_width))
sys.stdout.flush()
# each hash represents 2 % of the progress
for i in range(toolbar_width):
    sys.stdout.write("\r") # return to start of line
    sys.stdout.flush()
    sys.stdout.write("[")#Overwrite over the existing text from the start 
    sys.stdout.write("#"*(i+1))# number of # denotes the progress completed 
    sys.stdout.flush()
    time.sleep(0.1)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.