Python Progress Bar


307

ฉันจะใช้แถบความคืบหน้าได้อย่างไรเมื่อสคริปต์ของฉันทำงานบางอย่างที่อาจต้องใช้เวลา?

ตัวอย่างเช่นฟังก์ชั่นที่ใช้เวลาในการทำให้สมบูรณ์และส่งคืนTrueเมื่อเสร็จสิ้น ฉันจะแสดงแถบความคืบหน้าในช่วงเวลาที่ฟังก์ชั่นกำลังทำงานอยู่ได้อย่างไร?

โปรดทราบว่าฉันต้องการให้เป็นแบบเรียลไทม์ดังนั้นฉันจึงไม่สามารถคิดได้ว่าจะทำอย่างไรกับมัน ฉันต้องการสิ่งthreadนี้หรือไม่? ฉันไม่รู้.

ตอนนี้ฉันไม่ได้พิมพ์อะไรเลยในขณะที่ฟังก์ชั่นกำลังทำงาน แต่แถบความคืบหน้าก็ดี นอกจากนี้ฉันยังสนใจในสิ่งที่สามารถทำได้จากมุมมองโค้ด


คุณใช้ชุดเครื่องมือ GUI หรือ CLI เท่านั้น
Bobby

CLI แต่ฉันสามารถใช้ห้องสมุดบุคคลที่สามซึ่งไม่มีปัญหา ด้วย GUI ฉันสามารถทำได้ แต่ฉันสนใจในส่วนของ CLI
user225312

1
การทำซ้ำแถบความคืบหน้าของข้อความที่เป็นไปได้ในคอนโซล โปรดทราบว่าในขณะที่คำถามนี้ถูกโพสต์เมื่อสามวันก่อนหน้าคำถามที่เชื่อมโยงนั้นจะถูกดูบ่อยขึ้น
Greenstick

นี่คือวิธีแก้ปัญหาสำหรับภายใน Jupyter Notebook: mikulskibartosz.name/…
Steven C. Howell

ฉันได้เผยแพร่แถบความคืบหน้ารูปแบบใหม่ซึ่งคุณสามารถพิมพ์ดูปริมาณงานและอื่น ๆ ได้แม้กระทั่งหยุดชั่วคราวนอกจากภาพเคลื่อนไหวที่ยอดเยี่ยม! โปรดดู: github.com/rsalmei/alive-progress ! มีชีวิตอยู่ความคืบหน้า
rsalmei

คำตอบ:


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เป็นทางแยกของProgressBarที่ไม่ได้รับการปรับปรุงในปี


14
นี้ไม่ได้ปรับขนาดสำหรับหลายขั้นตอน ... pypi.python.org/pypi/progressง่ายมากที่จะใช้
m13r

5
ฉันลองรหัสนี้แล้วมันเกิดNameError: name 'xrange' is not definedข้อผิดพลาด ฉันไม่มีโมดูลหรือไม่
Mushroom Man

6
@ GokuMcSpock9733 คุณใช้ Python เวอร์ชันใดอยู่ งูหลาม 2 xrangeเป็นงูใหญ่ range3
quapka

9
นี่ไม่ควรเป็นคำตอบที่ดีที่สุด คำตอบอื่น ๆ (ที่มี tqdm) ดีกว่ามากสำหรับฉันอย่างน้อย
Florian

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 ตั้งแต่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สามารถเพิ่มได้TqdmExperimentalWarning: GUI is experimental/alphaคุณสามารถเพิกเฉยได้โดยใช้warnings.simplefilter("ignore")แต่จะไม่สนใจคำเตือนทั้งหมดในรหัสของคุณหลังจากนั้น


9
นี่เป็นทางออกเดียวที่ฉันพบว่าทำงานร่วมกับเทอร์มินัล qtconsole และโน้ตบุ๊ก
Ivelin

3
มันทำงานกับ iterable ใด ๆ ฉันมีปัญหาในการทำให้ใช้งานได้กับรายการสตริง
Josh Usre

3
@JoshUsre ใช่มันควรจะทำงานร่วมกับ iterable ใด ๆ ในขณะที่ฉันไม่เห็น iterable ใด ๆ มันสำลัก อย่างไรก็ตามการแสดงผลของการทางพิเศษแห่งประเทศไทย (เวลาที่เหลือ) ต้องใช้ iterable จะมี__len__สถานที่ให้บริการหรือผู้ใช้ต้องใส่อาร์กิวเมนต์total tqdmอื่น ๆ บาร์จะทำงาน แต่ไม่มี ETA
gaborous

6
@gaborous: ทำไมคำตอบนี้ถึงไม่ถูกโหวต? โซลูชันที่เรียบง่ายนี้ทำงานได้ทั้งใน terminal และใน Jupyter ซึ่งแตกต่างจากคำตอบยอดนิยม
Ébe Isaac

6
from tqdm import tqdm_notebook as tqdmสำหรับการทำงานในการใช้งานโน้ตบุ๊ค jupyter มิฉะนั้นจะไม่เขียนลงในหนึ่งบรรทัด
Jacques MALAPRADE

81

คำแนะนำข้างต้นค่อนข้างดี แต่ฉันคิดว่าคนส่วนใหญ่แค่ต้องการโซลูชันสำเร็จรูปโดยไม่ต้องพึ่งพาแพ็คเกจภายนอก แต่สามารถใช้ซ้ำได้

ฉันได้คะแนนที่ดีที่สุดจากทั้งหมดข้างต้นและทำให้มันเป็นฟังก์ชั่นพร้อมกับกรณีทดสอบ

หากต้องการใช้งานเพียงคัดลอกบรรทัดใต้ "def update_progress (คืบหน้า)" แต่ไม่ใช่สคริปต์ทดสอบ อย่าลืมนำเข้าระบบ เรียกสิ่งนี้เมื่อใดก็ตามที่คุณต้องการแสดงหรืออัพเดตแถบความคืบหน้า

สิ่งนี้ทำงานได้โดยส่งสัญลักษณ์ "\ 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% และไม่เคยแสดงผลเลย
Nick Humrich

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ตัวอย่างเช่น

  • ทำงานร่วมกับ iterable ใด ๆมันหมายถึงสิ่งที่len()สามารถใช้กับ listเป็นdictอะไรตัวอย่างเช่น['a', 'b', 'c' ... 'g']

นอกจากนี้คุณยังสามารถเปลี่ยนผลลัพธ์โดยการเปลี่ยนไฟล์sys.stderrเป็นตัวอย่าง


ฉันชอบวิธีนี้กำเนิดจะโยนข้อผิดพลาดดังต่อไปนี้:TypeError: object of type 'generator' has no len()
349

@jabellcu ในกรณีที่ ( generators) list()คุณต้องห่อมันด้วย ชอบfor i in progressbar(list(your_generator), "Computing: ", 40):
eusoubrasileiro

22

สำหรับแอพพลิเคชั่นที่คล้ายกัน (การติดตามความคืบหน้าในลูป) ฉันใช้python-progressbar :

ตัวอย่างของพวกเขาทำอะไรแบบนี้

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

เพิ่งลองสิ่งนี้ ใช้งานง่ายมาก ใช้เวลาประมาณ 2 นาที (รวมถึงความคืบหน้าในการติดตั้ง pip) เพื่อให้แถบสถานะเริ่มทำงาน
perelin

progressทำให้บาร์ดี แต่ล้มเหลวถ้าซอฟแวร์อื่น ๆ stderrคือการจัดการกับ ขออภัยฉันไม่ได้ตรวจสอบปัญหาที่แน่นอน
อาร์เธอร์

มันพิมพ์หนึ่งบรรทัดสำหรับแต่ละความคืบหน้าในคอนโซล ubuntu ของฉันเช่นถ้า max = 20 จะพิมพ์ 20 บรรทัด ... ฉันจะทำให้มันพิมพ์ได้เพียงหนึ่งบรรทัดได้อย่างไร
L's World

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
เยี่ยมมากขอบคุณสำหรับสิ่งนี้ BTW คุณสามารถเพิ่มการprogress.currentเพิ่มในตอนท้ายของ__call__เพื่อ จำกัด การโต้ตอบกับวัตถุจากรหัสหลักมากยิ่งขึ้น
npit

รหัสนี้ง่ายกระชับและมีประโยชน์! ขอบคุณ!
Ian Rehwinkel

15

ฉันชอบคำตอบของ Brian Khuuสำหรับความเรียบง่ายและไม่จำเป็นต้องใช้แพ็คเกจภายนอก ฉันเปลี่ยนมันเล็กน้อยดังนั้นฉันจึงเพิ่มรุ่นของฉันที่นี่:

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ในที่ที่อยู่ข้างใน! หากฟังก์ชั่นที่มีราคาแพงมีห่วงสำหรับเพียงแค่ใส่มัน คุณควรรู้ในตอนท้ายว่าจะให้ผลตอบแทนเท่าใดเพื่อให้ได้ผลลัพธ์ที่ดีที่สุด

ด้วยวิธีนี้ฟังก์ชั่นของคุณอาจเป็นแบบนี้:

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)

คำเตือน: ฉันเป็นผู้เขียน alive_progress แต่มันควรจะแก้ปัญหาของคุณได้อย่างดี อ่านเอกสารที่https://github.com/rsalmei/alive-progressนี่คือตัวอย่างของสิ่งที่สามารถทำได้:

มีชีวิตความคืบหน้า


8

ฉันชอบpython-progressbarมาก ๆ เพราะมันใช้ง่ายมาก

สำหรับกรณีที่ง่ายที่สุดเป็นเพียง:

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

หากเป็นลูปขนาดใหญ่ที่มีการวนซ้ำคงที่ซึ่งใช้เวลานานมากคุณสามารถใช้ฟังก์ชั่นนี้ที่ฉันทำ การวนซ้ำแต่ละครั้งจะเพิ่มความคืบหน้า โดยที่ count คือการวนซ้ำปัจจุบันของ loop ทั้งหมดคือค่าที่คุณวนลูปและขนาด (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
Etienne

4

รหัสด้านล่างเป็นคำตอบที่ค่อนข้างทั่วไปและยังมีเวลาที่ผ่านไปและเวลาที่เหลือโดยประมาณ คุณสามารถใช้ iterable ใด ๆ กับมัน แถบความคืบหน้ามีขนาดคงที่ 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

เมื่อทำงานในสมุดบันทึก jupyter การใช้ 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

ฉันชอบคำตอบของกาเบรียลแต่ฉันเปลี่ยนให้ยืดหยุ่น คุณสามารถส่งแถบความยาวไปยังฟังก์ชันและรับแถบความคืบหน้าของคุณด้วยความยาวที่คุณต้องการ และคุณไม่มีแถบความคืบหน้าที่มีความยาวเป็นศูนย์หรือลบ นอกจากนี้คุณยังสามารถใช้ฟังก์ชั่นนี้ได้เช่นGabriel answer (ดูตัวอย่างที่ 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 Console

มันใช้งานง่ายมาก รหัสต่อไปนี้:

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

นอกจากนี้คุณยังสามารถใช้Enlighten ข้อได้เปรียบหลักคือคุณสามารถเข้าสู่ระบบในเวลาเดียวกันโดยไม่ต้องเขียนทับแถบความคืบหน้าของคุณ

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

นี่คือ subclass แบบกำหนดเองที่ฉันเขียนเพื่อจัดรูปแบบเวลา 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-strings"ตามที่แนะนำใน 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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.