Thanh tiến trình Python


307

Làm cách nào để sử dụng thanh tiến trình khi tập lệnh của tôi đang thực hiện một số tác vụ có thể mất thời gian?

Ví dụ, một chức năng cần một chút thời gian để hoàn thành và trả về Truekhi hoàn thành. Làm cách nào để hiển thị thanh tiến trình trong thời gian chức năng được thực thi?

Lưu ý rằng tôi cần điều này trong thời gian thực, vì vậy tôi không thể biết phải làm gì về nó. Tôi có cần một threadcái này không? Tôi không có ý kiến.

Ngay bây giờ tôi không in bất cứ thứ gì trong khi chức năng đang được thực thi, tuy nhiên một thanh tiến trình sẽ rất tốt. Ngoài ra tôi quan tâm nhiều hơn đến cách làm điều này có thể được thực hiện từ quan điểm mã.


Bạn đang sử dụng bộ công cụ GUI hay chỉ CLI?
Bobby

CLI. Nhưng tôi có thể sử dụng thư viện của bên thứ ba, điều đó không có vấn đề gì. Với GUI tôi có thể làm điều này, nhưng tôi quan tâm đến phần CLI.
user225312

1
Bản sao có thể có của Thanh tiến trình văn bản trong Bảng điều khiển Lưu ý rằng trong khi câu hỏi này được đăng trước đó ba ngày, câu hỏi được liên kết thường được xem nhiều hơn.
Greenstick

Đây là một giải pháp cho Máy tính xách tay Jupyter: mikulskibartosz.name/ Kẻ
Steven C. Howell

Tôi đã xuất bản một loại thanh tiến trình mới, bạn có thể in, xem thông lượng và eta, thậm chí tạm dừng nó, bên cạnh các hình ảnh động rất tuyệt! Xin hãy xem: github.com/rsalmei/alive-proceed ! sống tiến bộ
rsalmei

Câu trả lời:


185

Có những thư viện cụ thể ( như cái này ở đây ) nhưng có lẽ một cái gì đó rất đơn giản sẽ làm:

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

Lưu ý: Progressbar2 là một nhánh của thanh tiến trình không được duy trì trong nhiều năm.


14
điều này không mở rộng cho nhiều bước ... pypi.python.org/pypi/proceed dễ sử dụng hơn nhiều
m13r

5
Tôi đã thử mã này, và nó đã ném một NameError: name 'xrange' is not definedlỗi. Tôi có thiếu một mô-đun không?
Người đàn ông nấm

6
@ GokuMcSpock9733 Bạn đang sử dụng phiên bản Python nào? Python 2 xrangelà 3 của Python range.
quapka

9
Đây không phải là câu trả lời hàng đầu. Câu trả lời khác (với tqdm) ít nhất là tốt hơn cho tôi.
Florian

1
Thanh tiến trình của người nghèo trong Python 3:print('■', end='', flush=True)
PatrickT

351

Với tqdm, bạn có thể thêm đồng hồ đo tiến độ vào các vòng lặp của mình trong một giây:

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]

Ngoài ra, có một phiên bản đồ họa của tqdm kể từ 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)

cửa sổ guq tqdm

Nhưng hãy cẩn thận, vì tqdm_guicó thể tăng a TqdmExperimentalWarning: GUI is experimental/alpha, bạn có thể bỏ qua nó bằng cách sử dụng warnings.simplefilter("ignore"), nhưng nó sẽ bỏ qua tất cả các cảnh báo trong mã của bạn sau đó.


9
Đây là giải pháp duy nhất tôi tìm thấy để làm việc với thiết bị đầu cuối, qtconsole và máy tính xách tay
Ivelin

3
Nó có hoạt động với bất kỳ lặp đi lặp lại? Tôi đã gặp khó khăn khi làm cho nó hoạt động với một danh sách các chuỗi.
Josh Usre

3
@JoshUsre Có, nó nên hoạt động với bất kỳ lần lặp nào, hiện tại tôi không thấy bất kỳ lần lặp nào mà nó bị nghẹn. Tuy nhiên, việc hiển thị ETA (thời gian còn lại) yêu cầu iterable phải có thuộc __len__tính hoặc người dùng phải cung cấp totalđối số tqdm. Khác, thanh sẽ hoạt động nhưng không có ETA.
gabious

6
@gabious: Tại sao đây không phải là câu trả lời được bình chọn hàng đầu? Giải pháp đơn giản này hoạt động cả trong thiết bị đầu cuối và trong máy tính xách tay Jupyter không giống như câu trả lời hàng đầu.
Ébe Isaac

6
để chạy trong một máy tính xách tay jupyter sử dụng from tqdm import tqdm_notebook as tqdm. Mặt khác không viết nó trên một dòng.
Jacques MALAPRADE

81

Các đề xuất trên là khá tốt, nhưng tôi nghĩ rằng hầu hết mọi người chỉ muốn một giải pháp đã sẵn sàng, không phụ thuộc vào các gói bên ngoài, nhưng cũng có thể tái sử dụng.

Tôi đã nhận được những điểm tốt nhất của tất cả những điều trên, và biến nó thành một chức năng, cùng với một trường hợp thử nghiệm.

Để sử dụng nó, chỉ cần sao chép các dòng trong "def update_proTHER (tiến trình)" chứ không phải tập lệnh thử nghiệm. Đừng quên nhập sys. Gọi đây bất cứ khi nào bạn cần để hiển thị hoặc cập nhật thanh tiến trình.

Điều này hoạt động bằng cách gửi trực tiếp biểu tượng "\ r" đến bàn điều khiển để di chuyển con trỏ trở lại điểm bắt đầu. "in" trong python không thu hồi biểu tượng trên cho mục đích này, do đó chúng ta cần '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)

Đây là kết quả của tập lệnh thử nghiệm hiển thị (Thanh tiến trình cuối cùng hoạt hình):

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
Thử nghiệm hoạt hình (lần cuối) sẽ in range(101)không phải là 100, tiến độ dừng ở mức 99% và không bao giờ hiển thị được thực hiện.
Nick Humrich

41

Câu trả lời này không phụ thuộc vào các gói bên ngoài , tôi cũng nghĩ rằng hầu hết mọi người chỉ muốn một đoạn mã làm sẵn . Mã dưới đây có thể được điều chỉnh để phù hợp với nhu cầu của bạn bằng cách tùy chỉnh: biểu tượng tiến trình '#'thanh size, thanh , văn bản, prefixv.v.

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

Sử dụng:

import time

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

Đầu ra:

Computing: [################........................] 4/15
  • Không yêu cầu một chủ đề thứ hai . Một số giải pháp / gói trên yêu cầu. Một chủ đề thứ hai có thể là một vấn đề, jupyter notebookví dụ, a.

  • Hoạt động với bất kỳ lần lặp nào, nó có nghĩa là bất cứ điều gì len()có thể được sử dụng trên. A list, a dictcủa bất cứ điều gì chẳng hạn['a', 'b', 'c' ... 'g']

Bạn cũng có thể thay đổi đầu ra bằng cách thay đổi tập tin thành sys.stderrví dụ


Tôi thích giải pháp này, máy phát điện sẽ đưa ra lỗi sau:TypeError: object of type 'generator' has no len()
jabellcu

@jabellcu trong trường hợp đó ( generators) bạn phải bọc nó bằng a list(). Giống nhưfor i in progressbar(list(your_generator), "Computing: ", 40):
eusoubrasileiro

22

đối với một ứng dụng tương tự (theo dõi tiến trình trong một vòng lặp) Tôi chỉ đơn giản sử dụng thanh python-Progress :

Ví dụ của họ đi một cái gì đó như thế này,

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
Để tương thích với Python 3, hãy thử progressbar2gói. Mã ở trên sẽ làm việc với nó.
d33tah

2
Bạn đã thực sự chỉ sử dụng import *?
eric

20

Hãy thử tiến bộ từ https://pypi.python.org/pypi/proTHER .

from progress.bar import Bar

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

Kết quả sẽ là một thanh như sau:

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

Chỉ cần thử điều này. RẤT dễ sử dụng. Mất 2 phút (bao gồm cả tiến trình cài đặt pip) để có một thanh trạng thái hoạt động.
perelin

progresslàm cho các thanh đẹp, nhưng nó thất bại nếu phần mềm khác đang thao tác stderr. xin lỗi, nhưng tôi đã không điều tra vấn đề chính xác
Arthur

Nó in một dòng cho mỗi tiến trình trong bảng điều khiển Ubuntu của tôi, ví dụ: nếu max = 20, nó sẽ in 20 dòng ... Làm cách nào để tôi chỉ in một dòng?
Thế giới

19

Tôi vừa thực hiện một lớp tiến bộ đơn giản cho nhu cầu của mình sau khi tìm kiếm ở đây một giải pháp tương đương. Tôi nghĩ rằng tôi có thể một bài viết tốt.

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)

Thí dụ :

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

Sẽ in như sau:

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


3
Tuyệt vời, cảm ơn bạn vì điều này. BTW, bạn có thể thêm progress.currentgia tăng vào cuối __call__để hạn chế sự tương tác với đối tượng từ mã chính hơn nữa.
npit

Mã này là đơn giản, súc tích và hữu ích! Cảm ơn bạn!
Ian Rehwinkel

15

Tôi thích câu trả lời của Brian Khuu vì sự đơn giản và không cần các gói bên ngoài. Tôi đã thay đổi một chút để tôi thêm phiên bản của mình vào đây:

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)

Phải mất tổng số lần chạy ( total) và số lần chạy được xử lý cho đến nay ( progress) giả sử total >= progress. Kết quả trông như thế này:

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

14

Bạn có thể sử dụng 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)

Trong ví dụ này, thanh tiến trình đang chạy trong 5 phút và nó được hiển thị như thế:

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

Bạn có thể thay đổi nó và tùy chỉnh nó theo ý muốn.


11

Để sử dụng bất kỳ khung thanh tiến trình nào theo cách hữu ích, nghĩa là để có được phần trăm tiến độ thực tế và ETA ước tính, bạn cần có thể khai báo số bước sẽ có.

Vì vậy, chức năng tính toán của bạn trong một luồng khác, bạn có thể chia nó theo một số bước hợp lý không? Bạn có thể sửa đổi mã của nó?

Bạn không cần phải cấu trúc lại nó hoặc phân chia theo các phương thức thực tế, bạn chỉ có thể đặt một số chiến lược yieldở một số nơi bên trong nó! Nếu hàm đắt tiền có một vòng lặp for , chỉ cần đặt một cái trong đó. Cuối cùng, bạn chỉ nên biết bao nhiêu sản lượng sẽ được thực hiện, để có kết quả tốt nhất.

Bằng cách đó, chức năng của bạn có thể là một cái gì đó như thế này:

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

hoặc này:

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

Với loại chức năng đó, bạn có thể cài đặt:

pip install alive-progress

Và sử dụng nó như:

from alive_progress import alive_bar

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

Để có được một thanh tiến độ mát mẻ!

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

Tuyên bố miễn trừ trách nhiệm: Tôi là tác giả của live_prowards, nhưng nó sẽ giải quyết vấn đề của bạn tốt. Đọc tài liệu tại https://github.com/rsalmei/alive-proceed , đây là một ví dụ về những gì nó có thể làm:

sống tiến bộ


8

Tôi thực sự thích thanh tiến trình python , vì nó rất đơn giản để sử dụng.

Đối với trường hợp đơn giản nhất, nó chỉ là:

import progressbar
import time

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

Sự xuất hiện có thể được tùy chỉnh và nó có thể hiển thị thời gian còn lại ước tính. Ví dụ, sử dụng mã giống như trên nhưng với:

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

5

Nếu đó là một vòng lặp lớn với số lần lặp cố định đang mất rất nhiều thời gian bạn có thể sử dụng chức năng này tôi đã thực hiện. Mỗi lần lặp của vòng lặp thêm tiến trình. Trong đó số đếm là số lần lặp hiện tại của vòng lặp, tổng là giá trị bạn đang lặp và kích thước (int) là mức độ lớn mà bạn muốn thanh tăng theo 10 tức là (kích thước 1 = 10 ký tự, kích thước 2 = 20 ký tự)

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 + ']')

thí dụ:

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

đầu ra:

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

4

Sử dụng thư viện này: fish( GitHub ).

Sử dụng:

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

Chúc vui vẻ!


Điều đó là có thể. Bạn nên hỏi nhà phát triển hoặc để lại vé: github.com/lericson/fish .
Etienne

4

Mã dưới đây là một giải pháp khá chung chung và cũng có thời gian trôi qua và ước tính thời gian còn lại. Bạn có thể sử dụng bất kỳ lặp đi lặp lại với nó. Thanh tiến trình có kích thước cố định 25 ký tự nhưng nó có thể hiển thị các cập nhật trong 1% bước sử dụng các ký tự khối đầy đủ, một nửa và một phần tư. Đầu ra trông như thế này:

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

Mã với ví dụ:

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)

Đề xuất cải tiến hoặc ý kiến ​​khác được đánh giá cao. Chúc mừng!


3

Tôi thích trang này .

Bắt đầu với ví dụ đơn giản và chuyển sang phiên bản đa luồng. Sáng tạo. Không yêu cầu gói bên thứ 3.

Mã sẽ trông giống như thế này:

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)

Hoặc đây là ví dụ để sử dụng các luồng để chạy thanh tải quay trong khi chương trình đang chạy:

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

Nó khá đơn giản trong 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

Khi chạy trong máy tính xách tay jupyter, sử dụng tqdm bình thường không hoạt động, vì nó ghi đầu ra trên nhiều dòng. Sử dụng cái này thay thế:

import time
from tqdm import tqdm_notebook as tqdm

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

2

Nếu công việc của bạn không thể được chia thành các phần có thể đo lường được, bạn có thể gọi chức năng của mình trong một luồng mới và thời gian cần bao lâu:

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"

Bạn rõ ràng có thể tăng độ chính xác thời gian theo yêu cầu.


Trường hợp nào một công việc sẽ được đo trong mã trong câu trả lời?
unseen_rider

2

Tôi thích câu trả lời của Gabriel , nhưng tôi đã thay đổi nó thành linh hoạt. Bạn có thể gửi chiều dài thanh đến hàm và nhận thanh tiến trình của bạn với bất kỳ độ dài nào bạn muốn. Và bạn không thể có một thanh tiến trình với độ dài bằng 0 hoặc âm. Ngoài ra, bạn có thể sử dụng chức năng này như câu trả lời của Gabriel (Xem ví dụ # 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)

Kết quả:

Đây là một thanh tiến trình đơn giản.

Ví dụ 1

Tiến trình: [### -------] 30%

Ví dụ # 2

Tiến độ: [|||||||||||| ........] 60%

Làm xong.


2

Tôi đã sử dụng format()phương pháp để làm một thanh tải. Đây là giải pháp của tôi:

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

Đầu ra:

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

1

Đây là một giải pháp ngắn xây dựng thanh tải theo chương trình (bạn phải quyết định thời gian bạn muốn nó).

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

Hãy thử PyProg. PyProg là một thư viện mã nguồn mở cho Python để tạo các thanh & chỉ báo tiến trình siêu tùy biến.

Nó hiện đang ở phiên bản 1.0.2; nó được lưu trữ trên Github và có sẵn trên PyPI (Liên kết xuống bên dưới). Nó tương thích với Python 3 & 2 và nó cũng có thể được sử dụng với Qt Console.

Nó thực sự dễ sử dụng. Các mã sau đây:

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

sẽ sản xuất:

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

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

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

Tôi thực sự đã tạo PyProg vì tôi cần một thư viện thanh tiến trình đơn giản nhưng siêu tùy biến. Bạn có thể dễ dàng cài đặt nó với : pip install pyprog.

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


1

Bạn cũng có thể sử dụng khai sáng . Ưu điểm chính là bạn có thể đăng nhập cùng một lúc mà không ghi đè lên thanh tiến trình của bạn.

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

Nó cũng xử lý nhiều thanh tiến trình.

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

Sử dụng thư viện tiến độ !

pip install progress

Đây là một lớp con tùy chỉnh mà tôi đã viết để định dạng thời gian ETA / đã trôi qua thành một định dạng dễ đọc hơn:

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

Đây là giải pháp đơn giản của tôi:

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

Bạn nên liên kết thanh tiến trình với nhiệm vụ trong tay (để nó đo tiến trình: D). Ví dụ: nếu bạn đang FTP một tệp, bạn có thể yêu cầu ftplib lấy một bộ đệm kích thước nhất định, giả sử là 128K, sau đó bạn thêm vào thanh tiến trình của mình bất kể tỷ lệ phần trăm của kích thước tệp 128k. Nếu bạn đang sử dụng CLI và đồng hồ đo tiến độ của bạn dài 20 ký tự, bạn sẽ thêm một ký tự khi 1/20 tệp đã được chuyển.


Trong trường hợp của tôi, tôi đang sử dụng API và nó không cung cấp phương tiện nào để nhận các khối cụ thể. Cảm ơn cho ý tưởng mặc dù, nó là tốt đẹp.
user225312

0

@Massagran: Nó hoạt động tốt trong các chương trình của tôi. Hơn nữa, chúng ta cần thêm một bộ đếm để chỉ ra thời gian vòng lặp. Bộ đếm này đóng vai trò là đối số của phương thức update. Ví dụ: đọc tất cả các dòng của tệp kiểm tra và xử lý chúng trên một cái gì đó. Giả sử rằng hàm dosth()không quan tâm đến biến 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()

Biến ikiểm soát trạng thái pbarthông qua phương thứcupdate


0

một câu trả lời chung chung hơn của jelde015 (tất nhiên là tín dụng cho anh ta)

để cập nhật thanh tải thủ công sẽ là:

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)
                     + ']')

và gọi nó bằng cách:

loadingBar(7, 220, 40)

sẽ kết quả:

007/220 [=                                       ]  

chỉ cần gọi nó bất cứ khi nào bạn muốn với igiá trị hiện tại .

đặt sizesố lượng ký tự của thanh phải là


0

Đoán tôi hơi muộn nhưng điều này sẽ phù hợp với những người làm việc với các phiên bản hiện tại của python 3 , vì điều này sử dụng "chuỗi f" , như được giới thiệu trong 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')

Thí dụ

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

Đầu ra

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

0

Đây là một cách đơn giản để tạo một thanh tiến trình

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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.