[python] 파이썬 진행률 표시 줄

스크립트에서 시간이 걸리는 작업을 수행 할 때 진행률 표시 줄을 어떻게 사용합니까?

예를 들어 완료하는 데 시간이 걸리고 완료되면 반환되는 함수입니다 True. 함수가 실행되는 동안 진행률 표시 줄을 표시하려면 어떻게해야합니까?

실시간으로해야하므로 어떻게해야하는지 알 수 없습니다. thread이것을 위해 필요 합니까? 나도 몰라

현재 함수가 실행되는 동안 아무것도 인쇄하지 않지만 진행률 표시 줄은 좋을 것입니다. 또한 코드 관점 에서이 작업을 수행하는 방법에 더 관심이 있습니다.



답변

특정 라이브러리 ( here와 같은 )가 있지만 매우 간단한 작업이 있습니다.

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 는 몇 년 동안 유지되지 않은 진행률 표시 줄 입니다.


답변

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]

또한 v2.0.0( d977a0c) 이후 tqdm의 그래픽 버전이 있습니다 .

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")있지만 코드 이후의 모든 경고는 무시합니다.


답변

위의 제안은 꽤 좋지만 대부분의 사람들은 외부 패키지에 의존하지 않고 이미 준비된 솔루션을 원하지만 재사용 할 수 있다고 생각합니다.

나는 위의 모든 것의 가장 좋은 점을 얻었고 그것을 테스트 케이스와 함께 기능으로 만들었습니다.

사용하려면 테스트 스크립트가 아닌 “def update_progress (progress)”아래의 행을 복사하십시오. sys를 가져 오는 것을 잊지 마십시오. 진행률 표시 줄을 표시하거나 업데이트해야 할 때마다 이것을 호출하십시오.

이것은 “\ r”기호를 콘솔에 직접 전송하여 커서를 시작으로 다시 이동시키는 방식으로 작동합니다. 파이썬의 “print”는 이러한 목적으로 위의 기호를 기억하지 않으므로 ‘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


답변

이 답변은 외부 패키지에 의존하지 않으며 대부분의 사람들은 기성품 코드를 원한다고 생각합니다 . 아래 코드는 bar progress symbol '#', bar size, text 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() 사용할 수 있으며 사용할 수있는 모든 것을 의미 합니다. A list, dict예를 들어 무엇이든['a', 'b', 'c' ... 'g']

sys.stderr예를 들어 파일을 변경하여 출력을 변경할 수도 있습니다


답변

비슷한 응용 프로그램 (루프에서 진행 상황을 추적)을 위해 간단히 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


답변

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


답변

방금 동등한 솔루션을 검색 한 후 내 요구에 맞는 간단한 진행 클래스를 만들었습니다. 나는 그것을 잘 게시 할 수 있다고 생각했습니다.

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